Рассмотрим следующий код:
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
был использован просто для простоты, чтобы представить механизм, вызывающий ошибку.
В начале этого года в новостной группе std-Discussion обсуждалось это: https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/h7jGY95j1oc
Похоже, что консенсус istream_iterator::reference
является T const&
для обеспечения соблюдения InputIterator
контракт; то есть, чтобы пользователи не писали *it = value;
, К сожалению, это также не позволяет перейти от кэшированного значения.
Как Т.С. упомянутое выше, разместите резолюцию на LWG2106 код скомпилируется; к сожалению, потому что move_iterator::reference
будет T const&&
он будет молча делать неправильные вещи, скорее всего, вызывая конструктор копирования вашего типа.
поскольку istream_iterator
изменяет кэшированное значение при увеличении, это (от языка POV) законно const_cast
возвращенная ссылка на T&
, К сожалению (опять же) это не помогает, так как нет простого способа вставить const_cast
между istream_iterator
а также move_iterator
,
Возможные обходные решения:
istream_iterator
с неконстантным 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>>;
Смотря на istream_iterator::reference
мы видим, что это T const &
, Разыменование итератора дает нам такую ссылку. Но чтобы быть в состоянии отойти от чего-то, это что-то должно быть изменяемым. Вот что сообщение об ошибке пытается сказать вам.
Вы могли бы сделать move_iterator
из istream_iterator
, поместив некоторый пользовательский итератор, который хранит внутреннее (неконстантное) хранилище между
Но почему вы хотите отойти от istream_iterator
? Те однопроходные итераторы, и, таким образом, вероятно, почти не имеют внутреннего хранилища.