可以从istream_iterator制作move_iterator吗?

时间:2015-08-13 10:13:45

标签: c++ c++11 iterator istream-iterator iterator-traits

请考虑以下代码:

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仅仅是为了简单起见而使用,以呈现导致错误的机制。

2 个答案:

答案 0 :(得分:1)

今年早些时候在std-discussion新闻组上对此进行了讨论:https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/h7jGY95j1oc

协商一致似乎是istream_iterator::reference T const&来执行InputIterator合同;也就是说,防止用户写*it = value;。不幸的是,这也阻止了从缓存值的移动。

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

由于istream_iterator在递增时修改了缓存的值,因此(从语言POV)合法到const_cast返回的T&引用。不幸的是(再次)在这里没有帮助,因为在const_castistream_iterator之间插入move_iterator并不容易。

可能的解决方案解决方案:

  • 使用非const istream_iterator typedef编写您自己的reference;
  • 撰写自己的move_iterator表演const_cast;
  • 编写一个插入const_cast迭代器;
  • 在值类型周围使用可变包装器。

后一种选择非常简单:

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

Example

答案 1 :(得分:0)

查看istream_iterator::reference,我们发现它是T const &。取消引用迭代器为我们提供了这样的参考。但是为了能够从某些东西转移,那些东西需要可以修改。这是错误消息试图告诉您的内容。

您可以通过放置一些自定义迭代器从move_iterator创建istream_iterator,该迭代器将内部(非常量)存储保存在其中。

但是你为什么要从istream_iterator转移?那些是单通道迭代器,因此几乎没有内部存储空间。