请考虑以下代码:
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 &&'
但是,如果分别用mstart
和meos
替换start
和eos
(常规迭代器),代码将会编译。为什么我无法制作move_iterators
?
修改
对于那些想知道我为什么要从流/字符串中移动字符的人。实际问题涉及比char
更复杂的数据类型,应避免从字符串复制。 char
仅仅是为了简单起见而使用,以呈现导致错误的机制。
答案 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::reference
将T const&&
,它会默默地做错事,很可能会调用你的类型的复制构造函数。
由于istream_iterator
在递增时修改了缓存的值,因此(从语言POV)合法到const_cast
返回的T&
引用。不幸的是(再次)在这里没有帮助,因为在const_cast
和istream_iterator
之间插入move_iterator
并不容易。
可能的解决方案解决方案:
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>>;
答案 1 :(得分:0)
查看istream_iterator::reference
,我们发现它是T const &
。取消引用迭代器为我们提供了这样的参考。但是为了能够从某些东西转移,那些东西需要可以修改。这是错误消息试图告诉您的内容。
您可以通过放置一些自定义迭代器从move_iterator
创建istream_iterator
,该迭代器将内部(非常量)存储保存在其中。
但是你为什么要从istream_iterator
转移?那些是单通道迭代器,因此几乎没有内部存储空间。