Почему std:: iterator не рекомендуется?

Класс шаблона std::iterator установлен для устаревания в С++ 17. Почему так? Это был удобный способ убедиться, что std::iterator_traits работает, особенно если вы можете использовать аргументы шаблона по умолчанию. Есть ли другой способ сделать это в С++ 17?

Ответ 1

Из предложение, которое предложило его отклонение:

В качестве помощи в написании классов итераторов исходная стандартная библиотека предоставила шаблон класса итератора для автоматизации объявления пяти типов typedef, ожидаемых от каждого итератора iterator_traits. Затем это использовалось в самой библиотеке, например, в спецификации std::ostream_iterator:

template <class T, class charT = char, class traits = char_traits<charT> >
class ostream_iterator:
  public iterator<output_iterator_tag, void, void, void, void>;

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

Вы также можете увидеть аргументы STL в LWG 2438. (h/t T.C.)


Что касается другого способа сделать это, на самом деле. В основном вы можете реализовать свою собственную версию std::iterator (которая не слишком сложна) или вручную выписать все эти typedef (что тоже не слишком сложно, и я на самом деле предпочитаю это для ясности).