Дано:
struct Iter {
using value_type = int;
using difference_type = int;
using reference = int;
using pointer = int;
using iterator_category = int;
};
Следующее прекрасно работает с libstc ++, но не компилируется с libc ++ 5.0.0:
#include <iterator>
#include <type_traits>
static_assert(
std::is_same<
std::iterator_traits<Iter>::iterator_category,
Iter::iterator_category
>::value, "");
С ошибкой:
ошибка: нет члена с именем ‘
iterator_category
‘ в ‘std::__1::iterator_traits<Iter>
‘
std::is_same<std::iterator_traits<Iter>::iterator_category, Iter::iterator_category>::value, "");
Статическое утверждение успешно выполняется, если Iter::iterator_category
является одной из стандартных категорий ввода, например, std::input_iterator_tag
,
ИМХО, он не должен потерпеть неудачу, потому что проект C ++ заявляет в [Iterator.traits] # 2:
Если Итератор имеет действительный ([Temp.deduct]) типы членов
difference_type
,value_type
,pointer
,reference
, а такжеiterator_category
,iterator_traits<Iterator>
иметь в качестве публично доступных членов:using difference_type = typename Iterator::difference_type; using value_type = typename Iterator::value_type; using pointer = typename Iterator::pointer; using reference = typename Iterator::reference; using iterator_category = typename Iterator::iterator_category;
Иначе,
iterator_traits<Iterator>
не должен иметь членов с любым из вышеперечисленных имен.
Кто-нибудь может объяснить, является ли это ошибкой реализации или почему мои ожидания ошибочны?
У нас также есть, в [std.iterator.tags]:
Зачастую для специализации шаблона функции желательно выяснить, какая категория является наиболее конкретной категорией аргумента итератора, чтобы функция могла выбрать наиболее эффективный алгоритм во время компиляции. Чтобы облегчить это, библиотека вводит классы тегов категорий, которые используются как теги времени компиляции для выбора алгоритма. Они есть:
input_iterator_tag
,output_iterator_tag
,forward_iterator_tag
,bidirectional_iterator_tag
а такжеrandom_acces_iterator_tag
, Для каждого итератора типаIterator
,iterator_traits<Iterator>::iterator_category
должен быть определен как наиболее конкретный тег категории, который описывает поведение итератора.namespace std { struct input_iterator_tag { }; struct output_iterator_tag { }; struct forward_iterator_tag: public input_iterator_tag { }; struct bidirectional_iterator_tag: public forward_iterator_tag { }; struct random_access_iterator_tag: public bidirectional_iterator_tag { }; }
int
не один из тех тегов, так iterator_traits<Iter>::iterator_category
не могу вернуть тебя int
, Я хотел бы предположить, что наличие недопустимой категории итераторов просто нарушает предварительные условия iterator_traits
— это не обязательно означает, что библиотека должна дать сбой, но это также не означает, что сбой является ошибкой библиотеки.
Тем не менее, эти предварительные условия не прописаны в [итераторах] так явно, как в других частях раздела библиотеки. Поэтому я склонен предположить, что обе библиотеки верны, но подход libc ++ не определяет псевдонимы членов в iterator_traits<Iter>
скорее всего лучше.
Других решений пока нет …