Как проверить, что переданный Iterator является итератором с произвольным доступом? - PullRequest
29 голосов
/ 29 ноября 2010

У меня есть следующий код, который выполняет некоторую арифметику итераторов:

template<class Iterator>
void Foo(Iterator first, Iterator last) {
  typedef typename Iterator::value_type Value;
  std::vector<Value> vec;
  vec.resize(last - first);
  // ...
}

Выражение (last - first) работает (AFAIK) только для итераторов с произвольным доступом (например, из vector и deque).Как я могу проверить в коде, что переданный итератор соответствует этому требованию?

Ответы [ 2 ]

33 голосов
/ 29 ноября 2010

Если Iterator является итератором с произвольным доступом, то

std::iterator_traits<Iterator>::iterator_category

будет std::random_access_iterator_tag.Самый простой способ реализовать это, вероятно, создать второй шаблон функции и заставить Foo вызывать его:

template <typename Iterator>
void FooImpl(Iterator first, Iterator last, std::random_access_iterator_tag) { 
    // ...
}

template <typename Iterator>
void Foo(Iterator first, Iterator last) {
    typedef typename std::iterator_traits<Iterator>::iterator_category category;
    return FooImpl(first, last, category());
}

Это дает то преимущество, что вы можете перегрузить FooImpl для разных категорий итераторов, если вы 'Мне нравится.

Скотт Мейерс обсуждает эту технику в одной из книг Effective C ++ (я не помню, какая именно).

4 голосов
/ 27 декабря 2017

В дополнение к отправке тега вы можете сравнить категорию с std::random_access_iterator_tag напрямую, используя std::is_same_v:

using category = typename std::iterator_traits<Iterator>::iterator_category;
if constexpr (std::is_same_v<category, std::random_access_iterator_tag>) {
  vec.resize(last - first);
}

Иногда это может привести к более ясному и лаконичному коду, особенно если только небольшая часть вашей реализации (например, резервирование размера вектора) зависит от категории итератора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...