Краткий ответ
Многие считают, что класс std::iterator
не предлагает много по сравнению с псевдонимами обычного типа, и даже немного запутывает их, не предоставляя явно имена и полагаясь на порядок параметров шаблона. Он устарел в C ++ 17 и, вероятно, исчезнет через несколько лет.
Это означает, что вы не должны больше использовать std::iterator
. Вы можете прочитать весь пост ниже, если вас интересует полная история (существует некоторая избыточность, поскольку она была начата до предложения об устаревании).
Наследственный ответ
Вы можете игнорировать все ниже, если вас не интересует история. Следующие фрагменты даже несколько раз противоречат сами себе.
На сегодняшний день (C ++ 11 / C ++ 14) стандарт, похоже, подразумевает, что больше не стоит наследовать от std::iterator
для реализации пользовательских итераторов. Вот краткое объяснение от N3931 :
Хотя стандарт допускал эту ошибку почти десятки раз, я рекомендую не указывать directory_iterator
и recursive_directory_iterator
как производные от std::iterator
, поскольку это является обязательным требованием для реализаций. Вместо этого они должны быть описаны как имеющие соответствующие typedefs, и разработчики должны сами решать, как их предоставлять. (Разница заметна для пользователей с is_base_of
, не то чтобы они задавали этот вопрос.)
[2014-02-08 Даниэль комментирует и предоставляет формулировку]
Эта проблема в основном схожа с тем решением, которое использовалось для устранения требования получения от unary_function
и друзей, как описано в N3198 , и я решительно настроен следовать этому духу. и здесь. Я хотел бы добавить, что в основном все «более новые» типы итераторов (такие как regex
связанный итератор) также не являются производными от std::iterator
.
В статье цитируется N3198 , которая сама утверждает, что она следует за амортизацией, обсужденной в N3145 . Причины отказа от классов, которые существуют только для предоставления typedef
s, приведены в следующем виде:
Наш опыт работы с концепциями вселяет в нас уверенность в том, что редко требуется зависеть от конкретных отношений классов, производных от базового класса, если доступность типов и функций достаточна. Новые языковые инструменты позволяют нам даже в отсутствие поддерживаемых языком концепций вывести существование типов названий в типах классов, что привело бы к гораздо более слабой связи между ними. Другим преимуществом замены наследования связанными типами является тот факт, что это уменьшит количество случаев, когда возникают неоднозначности: это может легко произойти, если тип наследует как от unary_function
, так и binary_function
(это имеет смысл, если функтор - это и унарный, и двоичный объект функции).
tl; dr : классы, которые предоставляют только typedef
s, теперь считаются бесполезными. Более того, они увеличивают связь, когда она не нужна, более многословны и могут иметь нежелательные побочные эффекты в некоторых угловых случаях (см. Предыдущую цитату).
Обновление: выпуск 2438 от N4245 , кажется, фактически противоречит тому, что я утверждал ранее:
Для удобства LWG девять итераторов STL изображены как производные от std::iterator
для получения их iterator_category
/ etc. Определения типов. К сожалению (и непреднамеренно), это также требует наследования, которое можно наблюдать (не только через is_base_of
, но и через разрешение перегрузки). Это вызывает сожаление, потому что это сбивает с толку пользователей, которые могут быть введены в заблуждение, полагая, что их собственные итераторы должны быть производными от std::iterator
, или что перегрузка функций для получения std::iterator
имеет какое-то значение. Это также непреднамеренно, потому что наиболее важные итераторы STL, контейнерные итераторы, не обязаны наследоваться от std::iterator
. (Некоторым даже разрешено быть необработанными указателями.) Наконец, это излишне ограничивает разработчиков, которые могут не захотеть наследовать от std::iterator
. (Например, для упрощения представлений отладчика.)
Подводя итог, я ошибся, @aschepler был прав: его можно использовать , можно , но это, конечно, не требуется - его тоже не обескураживают. Существует целое «давайте удалим std::iterator
», чтобы стандарт не ограничивал реализации стандартных библиотек.
Раунд 3: P0174R0 предлагает отказаться от std::iterator
для возможного удаления в будущем. Предложение уже довольно хорошо объясняет, почему оно должно быть объявлено устаревшим, так что мы идем:
Длинная последовательность аргументов void гораздо менее понятна для читателя, чем просто предоставление ожидаемых typedefs в самом определении класса, что является подходом, принятым в текущем рабочем проекте, следуя шаблону, установленному в C ++ 14, где мы устарел вывод всей библиотеки функторов из unary_function и binary_function.
В дополнение к уменьшенной ясности, шаблон итератора также создает ловушку для неосторожных, так как при обычном использовании это будет зависимый базовый класс, что означает, что он не будет изучаться во время поиска имени внутри класса или его класса. функции-члены. Это приводит к удивлению пользователей, пытающихся понять, почему не работает следующее простое использование:
#include <iterator>
template <typename T>
struct MyIterator : std::iterator<std::random_access_iterator_tag, T> {
value_type data; // Error: value_type is not found by name lookup
// ... implementations details elided ...
};
Одной только причины ясности было достаточно, чтобы убедить LWG обновить спецификацию стандартной библиотеки, чтобы больше не предписывать адаптерам стандартных итераторов как производным от std :: iterator, поэтому в самом стандарте больше не используется этот шаблон. Таким образом, это выглядит как сильный кандидат на амортизацию.
Это становится немного утомительно, и, похоже, не все с этим согласны, поэтому я позволю вам сделать свои собственные выводы. Если комитет в конечном итоге решит, что std::iterator
следует объявить устаревшим, то это даст понять, что вы больше не должны его использовать. Обратите внимание, что бумага для последующей обработки предлагает отличную поддержку для удаления std::iterator
:
Обновление от Джексонвилля, 2016:
Опрос: Устаревший iterator
для C ++ 17 ??
SF F N A SA
-10 1 0 0
В приведенных выше результатах опроса SF , F , N , A и SA обозначают Сильно для , Для , Нейтрально , Против и Сильно против .
Обновление от Оулу, 2016:
Опрос: Все еще не рекомендуется std::iterator?
SF F N A SA
3 6 3 2 0 * * тысяча сто сорок-девять
P0619R1 предлагает удалить std::iterator
, возможно, как только C ++ 20, а также предлагает улучшить std::iterator_traits
, чтобы он мог автоматически выводить типы difference_type
, pointer
и reference
так же, как std::iterator
, когда они явно не указаны.