我有一个链接的列表结构:
struct SomeLinkedList
{
const char* bar;
int lots_of_interesting_stuff_in_here;
DWORD foo;
SomeLinkedList* pNext;
};它是现有API的一部分,我不能更改它.
我想添加迭代器支持。boost::iterator_facade<>库似乎很适合这一目的。
class SomeIterator
: public boost::iterator_facade< SomeIterator,
const SomeLinkedList,
boost::forward_traversal_tag >
{
public:
SomeIterator() : node_( NULL ) {};
explicit SomeIterator( const SomeLinkedList* p ) : node_( p ) {};
private:
friend class boost::iterator_core_access;
void increment() { node_ = node_->pNext; };
bool equal( SomeIterator const& other ) const { /*some comparison*/; };
SomeLinkedList const& dereference() const { return *node_; };
SomeLinkedList const* node_;
}; // class SomeIterator目标是能够在标准库函数(如std::for_each )中使用它。
void DoSomething( const SomeLinkedList* node );
SomeLinkedList* my_list = CreateLinkedList();
std::for_each( SomeIterator( my_list ), SomeIterator(), DoSomething );不幸的是,我收到一个错误,它试图通过值而不是指针传递列表。
error C2664: 'void (const SomeLinkedList *)' : cannot convert parameter 1 from 'const SomeLinkedList' to 'const SomeLinkedList *'如何更改SomeIterator以使其正常工作?
谢谢,PaulH
编辑:我试过这样做:
class SomeIterator
: public boost::iterator_facade< SomeIterator,
SomeLinkedList,
boost::forward_traversal_tag,
SomeLinkedList* >
{
// ...但我发现了一个编辑错误:
error C2664: 'boost::implicit_cast' : cannot convert parameter 1 from 'SomeLinkedList **' to 'boost::detail::operator_arrow_proxy<T>编辑2:
我尝试过修改取消引用类型:
class SomeIterator
: public boost::iterator_facade< SomeIterator,
const SomeLinkedList,
boost::forward_traversal_tag >
{
// ...
const SomeLinkedList* dereference() const { return node_; };但是,我得到了最初的错误:
error C2664: 'void (const SomeLinkedList *)' : cannot convert parameter 1 from 'const SomeLinkedList' to 'const SomeLinkedList *'发布于 2010-08-18 17:04:28
当您的迭代器被取消引用时,它将返回一个const SomeLinkedList&,但是您的DoSomething函数需要一个const SomeLinkedList*。或者更改迭代器,以便在取消引用时以某种方式返回指针,或者更改DoSomething函数。
编辑以回应进一步的讨论:
我本人并没有实际使用boost::iterator_facade,但是看一看您发布的附加代码,您可能没有同时更改所有必要的部分。
你真的试过
class SomeIterator
: public boost::iterator_facade< SomeIterator,
SomeLinkedList,
boost::forward_traversal_tag,
SomeLinkedList* >
{和
const SomeLinkedList* dereference() const { return node_; };在一起?
或者如果这不起作用,那不如:
class SomeIterator
: public boost::iterator_facade< SomeIterator,
SomeLinkedList*,
boost::forward_traversal_tag>
{
const SomeLinkedList* dereference() const { return node_; };或者,正如达夫卡在评论中所建议的那样,如何通过在DoSomething周围设置一个包装器来解决指针与引用之间的问题?例如:
void DoSomethingWrapper( const SomeLinkedList& node )
{
DoSomething(&node);
}实际上,您甚至可以将包装器与它包装的函数保持相同的名称,并让重载规则在调用指针或引用版本时负责处理。
发布于 2011-10-31 04:26:40
我一直在努力理解boost::iterator_facade。寻找一个简单的例子,我找到了这个(旧的)问题和一个被接受的答案。我想我会张贴我需要的代码,使这个例子在这里工作,因为现有的问题和答案从来没有真正解决问题。
在第一个实例中,请注意,for_each()的第二个参数是一个结束迭代器。我发现在原始问题代码中使用的空迭代器(不确定这是正确的术语)工作良好,但前提是您完成了.equal()的不完整定义,如下所示;
bool equal( SomeIterator const& other ) const { return node_ == other.node_; }除此之外,简单地将DoSomething()参数的定义从ptr更改为引用(正如可接受的答案中提到的那样),是编译和运行该参数的关键。我在下面放了一些原始的测试代码来说明。
void DoSomething( const SomeLinkedList& node )
{
std::cout << "DoSomething " << node.foo << "\n";
}
int main()
{
SomeLinkedList temp[5];
memset(temp,0,sizeof(temp));
temp[0].pNext = &temp[1];
temp[1].pNext = &temp[2];
temp[2].pNext = &temp[3];
temp[3].pNext = &temp[4];
temp[4].pNext = 0;
temp[0].foo = 0;
temp[1].foo = 1;
temp[2].foo = 2;
temp[3].foo = 3;
temp[4].foo = 4;
SomeLinkedList* my_list = &temp[0];
std::for_each( SomeIterator( my_list ), SomeIterator(), DoSomething );
return 0;
}https://stackoverflow.com/questions/3514457
复制相似问题