Requirements包含*i++
,其等效表达式为
value_type x = *i;
++i;
return x;
如何在不实现标准后增量i++
的情况下声明这样的运算符,返回非void值(InputIterators不需要这样做)?
答案 0 :(得分:3)
您可以使用代理进行后期增量:
#include <iostream>
class input_iterator
{
private:
class post_increment_proxy
{
public:
post_increment_proxy(int value) : value(value) {}
int operator * () const { return value; }
private:
int value;
};
public:
post_increment_proxy operator ++ (int) {
post_increment_proxy result{value};
++value;
return result;
}
private:
int value = 0;
};
int main() {
input_iterator i;
std::cout << *i++ << '\n';
std::cout << *i++ << '\n';
std::cout << *i++ << '\n';
}
答案 1 :(得分:1)
首先,迭代器是可复制的,即使在InputIterator的情况下,复制更像是一个移动(具体地说,在你递增迭代器的任何一个副本之后,你不应该取消引用任何其他副本它)。
尽管如此,复制迭代器应该没有任何问题 - 事实上,大多数库(以及许多其他代码)都假定迭代器是“轻量级”对象;复制它们很便宜,所以(对于一个明显的例子)它们通常是按值传递的,而不是通过引用传递的。
因此,一个稍微简化的流迭代器可能看起来像这样:
template <class T>
class istream_iterator {
std::istream *is;
T data;
public:
istream_iterator(std::istream &is) : is(&is) { ++(*this); }
istream_iterator() : is(nullptr) { }
istream_iterator &operator++() { (*is) >> data; return *this; }
// So here's the post-increment: it just saves a copy of itself, then
// reads the next item (which increments the iterator), and finally
// returns the copied object, which will return the previously-read item
// from the stream when/if dereferenced.
istream_iterator operator++(int) {
// Note: this uses the compiler-generated copy constructor. Assuming
// a `T` is copy-constructible, this works fine--other than a T,
// we're only copying a pointer.
istream_iterator temp = *this;
(*is) >> data;
return temp;
}
T const &operator*() const { return data; }
bool operator !=(istream_iterator &end) { return (*is).good(); }
bool operator ==(istream_iterator &end) { return !(*is).good(); }
};
这会在一些相当小的点上“欺骗” - 例如,两个默认构造的迭代器应该相互比较相等,这不需要实现(实际上没有人使用或关心) 。在正常使用中,您从流中创建一个迭代器,而默认构造另一个迭代器。当且仅当第一个已经到达输入流的末尾时(或者由于某种原因读取失败,无论如何),两者之间的比较应该返回true。同样,这省略了实现operator->
,以及标准迭代器类型(value_type,traits_type,istream_type等)所需的一些typedef
。这些都与手头的问题无关虽然(并且所有都是添加所需代码的问题,而不是对已经存在的代码进行任何实质性更改。)
代码的快速演示可能如下所示:
int main() {
istream_iterator<char> i(std::cin), end;
while (i != end)
std::cout << *i++;
}
这会将字符从标准输入复制到标准输出,跳过空格,因为默认情况下operator>>
会跳过空格(但如果需要,可以使用noskipws
删除它。)