Подготовка к std::iterator устарела

21 марта комитет по стандартам проголосовал за утверждение амортизации std::iterator предложено в P0174:

Длинная последовательность пустых аргументов гораздо менее понятна читателю, чем просто предоставление ожидаемого typedef s в самом определении класса, который является подходом, принятым текущим рабочим проектом, следуя шаблону, установленному в C++14

До наследования C++17 от std::iterator Было рекомендовано удалить скуку из стандартной реализации итератора. Но для амортизации потребуется одна из следующих вещей:

  1. Теперь шаблон итератора должен будет включать все необходимые typedef s
  2. Алгоритмы работы с итераторами теперь нужно будет использовать auto вместо того, чтобы полагаться на итератор для объявления типов
  3. Локи Астари предположил, что std::iterator_traits может быть обновлен для работы без наследования от std::iterator

Может ли кто-нибудь объяснить мне, какой из этих вариантов мне следует ожидать, когда я разрабатываю собственные итераторы, ориентируясь на совместимость C++17?

2 ответа

Обсуждаемые альтернативы понятны, но я чувствую, что нужен пример кода.

Учитывая, что не будет никакой замены языка и не полагаясь на boost или на вашу собственную версию базового класса итератора, следующий код, который использует std::iterator будет зафиксирован в коде внизу.

С std::iterator

template<long FROM, long TO>
class Range {
public:
    // member typedefs provided through inheriting from std::iterator
    class iterator: public std::iterator<
                        std::forward_iterator_tag, // iterator_category
                        long,                      // value_type
                        long,                      // difference_type
                        const long*,               // pointer
                        const long&                // reference
                                      >{
        long num = FROM;
    public:
        iterator(long _num = 0) : num(_num) {}
        iterator& operator++() {num = TO >= FROM ? num + 1: num - 1; return *this;}
        iterator operator++(int) {iterator retval = *this; ++(*this); return retval;}
        bool operator==(iterator other) const {return num == other.num;}
        bool operator!=(iterator other) const {return !(*this == other);}
        long operator*() {return num;}
    };
    iterator begin() {return FROM;}
    iterator end() {return TO >= FROM? TO+1 : TO-1;}
};

(Код с http://en.cppreference.com/w/cpp/iterator/iterator с разрешения автора).

Без std::iterator

template<long FROM, long TO>
class Range {
public:
    class iterator {
        long num = FROM;
    public:
        iterator(long _num = 0) : num(_num) {}
        iterator& operator++() {num = TO >= FROM ? num + 1: num - 1; return *this;}
        iterator operator++(int) {iterator retval = *this; ++(*this); return retval;}
        bool operator==(iterator other) const {return num == other.num;}
        bool operator!=(iterator other) const {return !(*this == other);}
        long operator*() {return num;}
        // iterator traits
        using difference_type = long;
        using value_type = long;
        using pointer = const long*;
        using reference = const long&;
        using iterator_category = std::forward_iterator_tag;
    };
    iterator begin() {return FROM;}
    iterator end() {return TO >= FROM? TO+1 : TO-1;}
};

Вариант 3 является строго типизированной версией Варианта 1, так как вы должны писать все то же самое typedefs но дополнительно завернуть iterator_traits<X>,

Вариант 2 нежизнеспособен в качестве решения. Вы можете вывести некоторые типы (например, reference просто decltype(*it)), но вы не можете вывести iterator_category, Вы не можете различить input_iterator_tag а также forward_iterator_tag просто наличием операций, поскольку вы не можете рефлексивно проверить, удовлетворяет ли итератор многопроходной гарантии. Кроме того, вы не можете действительно различать те и output_iterator_tag если итератор выдает изменяемую ссылку. Они должны быть явно указаны где-то.

Это оставляет Вариант 1. Думаю, мы должны просто привыкнуть писать весь шаблон. Я, например, приветствую наших новых повелителей запястного канала.

Другие вопросы по тегам