Можно ли сделать move_iterator из istream_iterator?

Рассмотрим следующий код:

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 был использован просто для простоты, чтобы представить механизм, вызывающий ошибку.

4

Решение

В начале этого года в новостной группе 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>>;

пример.

1

Другие решения

Смотря на istream_iterator::referenceмы видим, что это T const &, Разыменование итератора дает нам такую ​​ссылку. Но чтобы быть в состоянии отойти от чего-то, это что-то должно быть изменяемым. Вот что сообщение об ошибке пытается сказать вам.

Вы могли бы сделать move_iterator из istream_iterator, поместив некоторый пользовательский итератор, который хранит внутреннее (неконстантное) хранилище между

Но почему вы хотите отойти от istream_iterator? Те однопроходные итераторы, и, таким образом, вероятно, почти не имеют внутреннего хранилища.

0

По вопросам рекламы [email protected]