2016-11-04 8 views
4

Я разрабатываю интерфейс C++, который позволяет пользователю выполнять итерацию объектов, декодированных из файла. Этот процесс декодирования несколько медленный.В C++, можно ли реализовать интерфейс итератора, в котором продвижение недействительности «текущего» элемента?

Я рассматриваю интерфейс итератора для этого, но я хочу, чтобы избежать какой-либо ненужной копии, так что я думаю о том (со стороны пользователя):

for (const auto& object : file) { 
    // you can access the members of `object` here 
    std::cout << object.whatever() << std::endl; 

    // you can copy `object` here 
    myObjectCopy = object; 

    // you CANNOT do this because `object` changes 
    // as soon as the iterator advances 
    myObjectPtr = &object; 
} 

object в предыдущем примере использования является ссылкой к объекту, внутреннему к экземпляру итератора.

Это не так? Какие еще идиоматические интерфейсы вы предложили бы здесь?

Я думал об интерфейсе потока (думаю std::istream), но AFAIK, методы для чтения данных также возвращают копии (они извлечь символы).

ответ

7

Похоже, что вы говорите, это an input iterator.

Обязательно наследуйте свой класс итератора от std::iterator<std::input_iterator_tag, decoded_object_type>. Классическая реализация - для operator* для кэширования декодированного объекта и возврата кэшированного объекта, если он вызывается второй раз перед вызовом operator++; и operator++, вызывающий operator*, чтобы убедиться, что объект декодируется, если его еще нет.

+1

Итераторам ввода разрешено указывать «вы можете только один раз вызывать' * ', и вы должны вызывать его перед' ++ '", и на самом деле имеют '*' продвижение, а '++' - это noop. Предоставление большего - это здорово, просто не требуется. – Yakk

+0

Но если '*' не вызывается, '++' все равно нужно продвигать итератор. Поэтому при таком подходе становится необходимым, чтобы '++' проверял, не '' '' '' '' не был вызван, и вызывать его сам. –

+0

Нет, я утверждаю, что это не требуется. '++' разрешено продвигаться, но это может быть noop. Его предварительное условие удовлетворяет его постусловию. Это может быть удивительно, но для большинства применений нам все равно. Существует * примечание * [здесь] (http://en.cppreference.com/w/cpp/concept/InputIterator), которое подразумевает вызов '(void) * i, * i' должен быть эквивалентен' * i', но примечания не являются нормативными; Я бы хотел дважды проверить стандарт. Возможно, я здесь слишком агрессивен, но я видел множество реализаций, которые делают именно это («читать» и «продвигать», «++» ничего не делать), так что я не люблю интерпретацию. – Yakk

2

Да, все в порядке. Iostream в основном тот же: если вы перебираете значения, которые вы получаете от него, вы можете их скопировать, но вы не можете удерживать указатель на них после того, как поток или итератор в потоке продвинут.