2015-12-10 2 views
0

Я просто заметил, что для класса итератора std::__detail::_Node_iterator (в libstdc GCC в ++, источник here), у нас есть operator++(), но не operator+(), так что вы можете использовать (my_set.cbegin()++)++ но вы не можете использовать my_set.cbegin() + 2.Почему некоторые итераторы libstdC++ имеют оператор ++, но не оператор +?

Почему? Это просто отсутствие синтаксического сахара или есть более глубокая причина?

ответ

1

Стандарт не предоставляет operator+, если это будет O (n), и удивит многих пользователей.

Он предоставляет функцию std::advance, которую вы можете использовать, если вы готовы заплатить.

1

Почему это? Это просто отсутствие синтаксического сахара или есть более глубокая причина?

Понимание того, что это могло бы быть немного спекулятивным с моей стороны (я не дизайн/реализацией итераторов), моя мысль в том, что итератор предназначен для обхода коллекции с некоторой степенью безопасности. Написание чего-то типа iterator++ безопасно доставит вас от существующего элемента в коллекции к следующему или автоматически укажет на null, если вы достигли конца.

Это также короче, чем написание iterator = iterator + 1 или iterator += 1, и это может быть основной причиной ограничения его только ++. Добавление всех из них представляется излишним и ненужным.

Цитирование из C++ Reference (курсив мой)

итератора является любой объект, который, указывая на какой-то элемент в диапазоне элементов (таких как массив или контейнер), имеет возможность выполнять итерацию через элементы этого диапазона с использованием набора операторов (с по наименьшим приращением (++) и разыменованием (*) операторов).

Исходя из этого, представляется намеренным архитектурным решением сохранить требования клиента для реализации итераторов до минимума. Обратите внимание, что на основании вышеизложенной формулировки (т. Е. «По крайней мере»), по-видимому, нет технической причины, почему кто-то не мог добавить поддержку для других операторов, включая операторы сравнения, отличные от !=. Должны ли они , вероятно, еще одно обсуждение.

Кроме того, итераторы обычно перемещают все объекты в пределах некоторого диапазона последовательно, поэтому разрешение iterator + X, по-видимому, будет идти против его намеченной цели в этом смысле.

Например, если вы делаете iterator + 2, откуда бы вы не узнали, что вы не просите больше, чем то, что действительно осталось от текущей позиции итератора? Вы могли бы попытаться пройти мимо конца коллекции и дождаться ошибки сегментации - или им нужно будет начать бросать исключения. Способность итератора до благополучно пересекать коллекцию, не выходя из пределов - это вы потеряете здесь, ИМХО.

Итератор предназначен только для защиты клиентов от деталей реализации коллекции. То есть, клиенту не нужно знать, реализована ли коллекция как массив, какой-то связанный список или какое-то дерево. Также не нужно учитывать количество элементов, которые имеет коллекция, что еще раз облегчает реализацию и работу. (У него есть отдельная ответственность.)

Основываясь на этом и сохраняя предыдущие данные о безопасности и минималистическом требовании, решение избежать использования каждого возможного оператора, который может поддерживать объект, имеет смысл для меня.

Смежные вопросы