Запрещает ли стандартная библиотека C ++ нестандартные категории итераторов?

0

Следующая программа, которая создает пользовательский тег категории итератора, отклоняется clang (используя -stdlib=libc++), но не другими компиляторами и стандартными реализациями библиотек:

#include <iterator>

struct my_iterator_tag {};

struct my_iterator : std::iterator<my_iterator_tag, int> {};

int main()
{
  std::iterator_traits<my_iterator>::value_type x;
  return 0;
}

Мне непонятно, запрещает ли стандарт C++ создавать экземпляр std::iterator_traits с типом итератора, который имеет нестандартную категорию итератора.

Является ли эта программа незаконной?

clang output (при использовании libc++) ниже:

$ clang -stdlib=libc++ test.cpp 
test.cpp:9:38: error: no type named 'value_type' in 'std::__1::iterator_traits<my_iterator>'
  std::iterator_traits<my_iterator>::value_type x;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
1 error generated.
Теги:
iterator

1 ответ

2

Шаблон std::iterator определяется следующим образом:

template<class Category, class T, class Distance = ptrdiff_t,
    class Pointer = T*, class Reference = T&> struct iterator {
    typedef T value_type;
    typedef Distance difference_type;
    typedef Pointer pointer;
    typedef Reference reference;
    typedef Category iterator_category;
  };
}

Я не вижу ничего плохого в вашем заявлении:

struct my_iterator : std::iterator<my_iterator_tag, int> {};

Итак, свободно говоря, вы в конечном итоге определяете:

struct my_iterator {

    // ...

    typedef Category my_iterator_tag;

    // ...
};

Не вижу ничего плохого в этом. Это действительное объявление.

Теперь давайте взглянем на определение iterator_traits:

template<class Iterator> struct iterator_traits {
   typedef typename Iterator::difference_type difference_type;
   typedef typename Iterator::value_type value_type;
   typedef typename Iterator::pointer pointer;
   typedef typename Iterator::reference reference;
   typedef typename Iterator::iterator_category iterator_category;
};

Применяя этот шаблон к Iterator my_iterator, я тоже не вижу ничего технически неправильного. Вышеприведенные определения этих шаблонов поднимаются прямо из стандарта. Итак, что касается фактического строго, буквального объявления этих шаблонов в стандарте C++ 11, я не вижу ничего плохого в объявлениях.

Стандарт C++, конечно, определяет пять стандартных категорий итераторов, поэтому, если остальная часть библиотеки C++, необходимо проанализировать это дальше. Я полагаю, что различные вещи, такие как адаптеры итератора, вероятно, будут неопределенным поведением, с чем-либо, кроме пяти стандартных категорий итераторов.

Я не мог найти с беглым взглядом все, что прямо указывает, что использование ничего, кроме пяти предопределенных тегов с std::iterator и std::iterator_traits является неопределенным поведением, поэтому в этом только ограниченном примере я бы сказал, что это технически обоснованно, хотя и имеет сомнительную ценность.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню