如何在 C++ 中为输入迭代器实现 "dereference and post-increment"?
How to implement "dereference and post-increment" for input iterator in C++?
Requirements for InputIterator include *i++
等效表达式为
value_type x = *i;
++i;
return x;
如何在不实现标准 post 增量 i++
返回非空值(InputIterators 不需要这样做)的情况下声明这样的运算符?
首先,迭代器是可复制的,即使在 InputIterator 的情况下,复制更像是一个移动(具体来说,在递增迭代器的任何一个副本后,您不应该取消引用任何其他副本它的副本)。
None尽管如此,复制迭代器应该没有任何问题——事实上,大多数库(以及许多其他代码)都假定迭代器是 "lightweight" 对象;复制它们很便宜,因此(举一个明显的例子)它们通常按值传递,而不是按引用传递。
因此,稍微简化的流迭代器可能看起来像这样:
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(); }
};
这个 "cheats" 关于几个相当小的要点——例如,两个默认构造的迭代器应该相互比较相等,这不需要费心去实现(而且几乎没有人使用过或关心)。在正常使用中,您从流创建一个迭代器,并默认构造另一个。两者之间的比较应该 return 当且仅当第一个已经到达输入流的末尾(或者由于某种原因读取失败,无论如何)。同样,这省略了实现 operator->
,以及标准迭代器类型所需的一些 typedef
(value_type、traits_type、istream_type 等) .) None 其中与手头的问题相关(所有这些都是添加所需代码的问题,而不是对此处已有的代码进行任何实质性更改)。
代码的快速演示可能如下所示:
int main() {
istream_iterator<char> i(std::cin), end;
while (i != end)
std::cout << *i++;
}
这会将字符从标准输入复制到标准输出,跳过白色 space,因为 operator>>
默认跳过白色 space(但您可以使用 [=15= 消除它] 如果你愿意的话)。
您可以为 post 增量使用代理:
#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';
}
Requirements for InputIterator include *i++
等效表达式为
value_type x = *i;
++i;
return x;
如何在不实现标准 post 增量 i++
返回非空值(InputIterators 不需要这样做)的情况下声明这样的运算符?
首先,迭代器是可复制的,即使在 InputIterator 的情况下,复制更像是一个移动(具体来说,在递增迭代器的任何一个副本后,您不应该取消引用任何其他副本它的副本)。
None尽管如此,复制迭代器应该没有任何问题——事实上,大多数库(以及许多其他代码)都假定迭代器是 "lightweight" 对象;复制它们很便宜,因此(举一个明显的例子)它们通常按值传递,而不是按引用传递。
因此,稍微简化的流迭代器可能看起来像这样:
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(); }
};
这个 "cheats" 关于几个相当小的要点——例如,两个默认构造的迭代器应该相互比较相等,这不需要费心去实现(而且几乎没有人使用过或关心)。在正常使用中,您从流创建一个迭代器,并默认构造另一个。两者之间的比较应该 return 当且仅当第一个已经到达输入流的末尾(或者由于某种原因读取失败,无论如何)。同样,这省略了实现 operator->
,以及标准迭代器类型所需的一些 typedef
(value_type、traits_type、istream_type 等) .) None 其中与手头的问题相关(所有这些都是添加所需代码的问题,而不是对此处已有的代码进行任何实质性更改)。
代码的快速演示可能如下所示:
int main() {
istream_iterator<char> i(std::cin), end;
while (i != end)
std::cout << *i++;
}
这会将字符从标准输入复制到标准输出,跳过白色 space,因为 operator>>
默认跳过白色 space(但您可以使用 [=15= 消除它] 如果你愿意的话)。
您可以为 post 增量使用代理:
#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';
}