Приращение префикса двунаправленного итератора С++

Наблюдение 1: выходной итератор C++ требует этого &r == &++r, в то время как входной итератор не упоминает это требование. См. [C++11: 24.2.{3,4}].

Наблюдение 2. Прямые, двунаправленные итераторы произвольного доступа удовлетворяют требованиям входных итераторов [24.2.{5,6,7}:1], но не обязательно требованиям выходных итераторов, если только они не являются изменяемыми [ 24.2.1:4].

Наблюдение 3. Двунаправленные итераторы добавляют операцию уменьшения префикса с требованием &r == &--r [24.2.6].

Итак, правда ли, что постоянный двунаправленный итератор должен удовлетворять &r == &--r, но не обязательно &r == &++r, а изменяемый двунаправленный итератор должен удовлетворять обоим?

Можете ли вы указать, как это требование может повлиять на реализацию?


MvG ниже задает вопрос, который я действительно имел в виду:

  • Когда постоянный итератор Forward имеет смысл не удовлетворять &r == &++r?

person nknight    schedule 10.08.2012    source источник


Ответы (2)


Это косвенный способ формулирования требований без явного указания конкретной реализации. В частности, &r == &++r — это способ сказать, что ++r не может возвращать прокси-объект. Результатом должен быть тот же итератор.

Здесь mutable не является полной противоположностью const в обычном смысле, но означает «доступный для записи» и снова относится к требованиям для итератора вывода.

Двунаправленный итератор, конечно, должен поддерживать как ++p, так и --p (по определению), но не должен быть доступен для записи/изменения.

Категории не совсем ортогональны между чтением/записью и перемещением вперед/назад, поэтому отдельные требования не являются независимыми, как могли бы быть. Это вызывает некоторую путаницу.

Я не уверен, следует ли ваш вывод из наблюдений, но не думаю, что это будет важной свободой для реализации. Тот факт, что вы должны поддерживать такие вещи, как *++p и *p++, устанавливает большинство ограничений.

person Bo Persson    schedule 10.08.2012

Можете ли вы указать, как это требование может повлиять на реализацию?

Очевидный ответ заключается в том, что метод operator++() или operator--() должен return *this, тогда как отдельная функция Foo& operator++(Foo& arg) должна возвращать свой аргумент. Поскольку это в любом случае разумно, большинству реализаций не о чем беспокоиться.

Более сложный вопрос: «Когда итератору (например, прямому вводу) имеет смысл не следовать описанному выше подходу». Я еще не мог привести разумный пример. Даже для константного итератора ввода тип ++r должен быть ссылкой на тип итератора. Таким образом, любая форма «прокси-объекта», как упоминал @Bo Persson в своем ответе, будет работать только в том случае, если этот прокси-объект был подкласс класса итератора. Кажется, это не имеет большого смысла.

У меня такое ощущение, что требование &r == &++r было просто забыто для случая итератора вывода. Я сомневаюсь, что авторы спецификации имели в виду какой-либо конкретный вариант использования, в котором это требование не было бы выполнено. Но я предполагаю, поэтому я с нетерпением жду более надежного ответа на этот вопрос.

person MvG    schedule 10.08.2012
comment
Спасибо за более сложный (и более интересный) вопрос. Это действительно то, к чему я клонил, поэтому я добавил это выше. - person nknight; 11.08.2012