可以从istream_iterator中生成move_iterator吗

Can one make move_iterator from istream_iterator?

本文关键字:iterator move istream      更新时间:2023-10-16

考虑以下代码:

typedef istream_iterator<char> char_itr ;
char_itr eos;
string ll("some text here");
istringstream line_in(ll);
char_itr start(line_in);
move_iterator<char_itr> mstart(start); // !!!
move_iterator<char_itr> meos(eos);
vector<char> vc(mstart, meos);

由于第(!!(行:,以上代码将无法编译

error C2440: 'return' : cannot convert from 'const char' to 'char &&'

但是,如果将mstartmeos分别替换为starteos(常规迭代器(,则代码将编译。为什么我不能制作move_iterators

编辑:对于那些想知道我为什么要从流/字符串中移动字符的人。实际问题涉及比char更复杂的数据类型,应该避免从字符串中复制。为了简单起见,使用char来呈现导致错误的机制。

今年早些时候,std讨论新闻组上对此进行了讨论:https://groups.google.com/a/isocpp.org/forum/#!主题/标准讨论/h7jGY95j1oc

一致认为istream_iterator::referenceT const&,以执行InputIterator合同;即防止用户写入CCD_ 11。不幸的是,这也阻止了从缓存值中移动。

如上所述,将决议发布到LWG2106,代码将编译;不幸的是,因为move_iterator::reference将是T const&&,所以它会默默地做错误的事情,很可能会调用您类型的复制构造函数。

由于istream_iterator在递增时会修改缓存的值,因此它(从语言POV(对于const_cast(返回的对T&的引用(是合法的。不幸的是(再次(,这在这里没有帮助,因为在istream_iteratormove_iterator之间没有简单的方法插入const_cast

可能的解决方案:

  • 编写您自己的istream_iterator,使用非常量的reference typedef
  • 编写自己的move_iterator执行const_cast
  • 编写一个插入式CCD_ 24迭代器
  • 在值类型周围使用可变包装器

后一种选择出奇地简单:

template<class T>
  struct mutable_wrapper {
    T mutable value;
    operator T&() const { return value; }
  };
// ...
using itr = std::istream_iterator<mutable_wrapper<MyType>>;

示例。

查看istream_iterator::reference,我们发现它是T const &。取消对迭代器的引用为我们提供了这样一个引用。但是,为了能够从某个事物中移动,该事物需要是可修改的。这就是错误消息试图告诉你的。

您可以从istream_iterator中生成move_iterator,方法是在其间放置一些自定义迭代器来保持内部(非常量(存储。

但你为什么要离开istream_iterator?这些是单遍迭代器,因此可能几乎没有内部存储。