我有一个产生值的类,其界面如下:
template<class T>
class Generator
{
public:
void advance();
T* get();
bool done();
//...
};
advance
函数使生产者前进并在内部存储中放置一个指向新值的指针。 get
函数返回此指针,如果nullptr
完成则返回Generator
(尽管Generator
在正常操作过程中可以生成nullptrs
)。如果done
完成生成值,Producer
将返回true。 get
返回一个指针,允许客户端与生成的值进行交互,从而可能将信息传回Generator
。
对于实现迭代器来说,这似乎非常简单。 Generator
类不可复制,因此它本身不能成为迭代器,所以我创建了一个带有nessesary操作的简单包装器。我遇到的问题是后增量算子;推进Generator
使旧指针无效。我已经玩过不同的想法,但没有一个允许我满足输入迭代器或输出迭代器的所有要求。我不希望我的迭代器有一个值的副本,因为我希望通过指针有引用语义。我最接近的是让迭代器存储一个增量计数器,并且仅在取消引用或比较操作时提前Generator
。这让人感到const_cast
,并且感到非常危险。有没有办法为这个接口实现正确的迭代器?
答案 0 :(得分:1)
根据您的描述,我认为您能做的最好的就是投入 迭代器。前向迭代器的一个保证是 他们是多遍的,我不知道你怎么能这样做 你的班。你的班级不支持记忆职位, 并从它重新启动,所以一旦一个迭代器前进,没有 其他人可以看到那个元素。
当然,你还可以做很多事情 输入迭代器,但如果它们不够,你就必须这样做 使用迭代器将值复制到向量中,然后迭代 在那之上。
编辑:
关于您对*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*
,一旦你恢复了回报
value,然后将其myOwner
设置为null,测试该案例
在析构函数中。)