我有一个生成值的类,具有如下接口(interface):
template<class T>
class Generator
{
public:
void advance();
T* get();
bool done();
//...
};
advance
函数使生产者前进,并在内部存储中放置一个指向新值的指针。 get
函数返回此指针,如果 Generator
已完成,则返回 nullptr
(尽管 Generator
可以生成 nullptrs
在正常操作过程中,也是如此)。如果 Producer
已完成生成值,则 done
返回 true。 get
返回一个指针,允许客户端与生成的值进行交互,可能会将信息传回给 Generator
。
这似乎很容易为它实现一个迭代器。 Generator
类不可复制,因此它本身不能是迭代器,因此我创建了一个包含必要操作的简单包装器。我遇到的问题是后增量运算符;推进 Generator
会使旧指针无效。我尝试过不同的想法,但没有一个能让我满足输入迭代器或输出迭代器的所有要求。我不希望我的迭代器拥有该值的拷贝,因为我希望通过指针获得引用语义。我最接近的是让迭代器存储一个增量计数器,并且只在取消引用或比较操作时推进 Generator
。这与 const_cast
相得益彰,而且感觉非常危险。有什么方法可以为此接口(interface)实现正确的迭代器吗?
最佳答案
根据你的描述,我认为你能做的最好的就是输入 迭代器。前向迭代器的保证之一是 它们是多 channel 的,我不知道你怎么能用 你的类。你的类(class)不支持背位置, 并从中重新启动,所以一旦一个迭代器前进,就没有了 的其他人可以看到该元素。
当然,您仍然可以使用 输入迭代器,但如果它们还不够,你将不得不 使用迭代器将值复制到 vector 中,然后迭代 在那之上。
编辑:
关于您对 *r++
工作必要性的评论:
我认为以下内容是合法的:
template <typename T>
class GeneratorIterator
{
class PostIncrProxy
{
GeneratorIterator* myOwner;
public:
PostIncrProxy( GeneratorIterator* owner )
: myOwner( owner )
{
}
~PostIncrProxy()
{
++(*myOwner);
}
T* operator*() const
{
return **myOwner;
}
};
Generator<T>* myOwner;
public:
GeneratorIterator( Generator<T>& owner )
: myOwner( &owner )
{
}
GeneratorIterator() // End iterator...
: myOwner( nullptr )
{
}
bool operator==( GeneratorIterator const& other ) const
{
return (myOwner == nullptr) == (other.myOwner == nullptr);
}
bool operator!=( GeneratorIterator const& other ) const
{
return !operator==( other );
}
T* operator*() const
{
assert( myOwner != nullptr );
return myOwner->get();
}
// -> not necessary if we're iterating over T*. If
GeneratorIterator& operator++()
{
assert( myOwner != nullptr );
myOwner->advance();
if ( myOwner->done() ) {
myOwner = nullptr;
}
}
PostIncrProxy operator++(int)
{
return PostIncrProxy( this );
}
};
这会将实际递增推迟到
完整的表达,我想这在某些方面可能是个问题
退化的案例,但我至少会尝试一下。 (如果更糟
最坏的情况是,您还可以在
PostIncrProxy::operator*
,一旦你恢复了返回
值,然后将其myOwner
设置为null,测试用例
在析构函数中。)
关于c++ - 将迭代器实现为具有引用语义的抽象生成器的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21413422/