4

考虑以下代码:

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 &&'

但是,如果您分别用and替换mstartand (常规迭代器),则代码将编译。为什么我做不出来?meosstarteosmove_iterators

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

4

2 回答 2

1

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

共识似乎istream_iterator::referenceT const&执行InputIterator合同;也就是防止用户写*it = value;。不幸的是,这也阻止了从缓存值移动。

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

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

可能的解决方法:

  • istream_iterator用非常量referencetypedef编写你自己的;
  • 写自己的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>>;

例子

于 2015-08-13T10:40:03.790 回答
0

看着istream_iterator::reference,我们看到它是T const &。取消引用迭代器为我们提供了这样的引用。但是为了能够从某事中转移出来,那某事需要是可修改的。这就是错误消息试图告诉您的内容。

您可以move_iterator通过istream_iterator放置一些在其间保持内部(非常量)存储的自定义迭代器来制作 a 。

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

于 2015-08-13T10:27:08.437 回答