2016-02-26 1 views
2

Следующая мета-функция вычисляет, если данный тип является случайным итератором доступа:мета функции с поведением по умолчанию на недостающем признаке и как обнаружить случайный доступ

template <class I> 
    struct is_random_access 
     : boost::is_convertible 
     < typename boost::iterator_traversal<I>::type 
     , boost::random_access_traversal_tag 
     > 
    {}; 

Теперь, конечно, это не будет работать, если I не является итератором вообще, как нет boost::iterator_traversal<I>.

Два независимых вопросы:

  1. Как сделать is_random_access возвращение ложным (а не ошибку компиляции), когда I не является итератор?
  2. Это хороший способ определить, является ли итератор случайным доступом к переходу?
+0

https://stackoverflow.com/questions/4307271/how-to-check-that-the-passed-iterator-is-a-random-access-iterator – Mine

+0

1. Я не хочу отмечать отправку. Я хочу, чтобы мета-функция была спрошена, чтобы работать. 2. не является std :: random_access_iterator_tag подмножеством random_access_traversal_tags (т. Е. Существуют итераторы с обратным ходом случайного доступа, которые не являются std :: random_access_iterator_tag)? – Nick

+0

Что-то вроде 'std :: условный > :: value, identity >, identity >> :: type :: type'. – Jarod42

ответ

2

Для вашего первого вопроса вы можете использовать SFINEA example from wikipedia:

template <class... Ts> using void_t = void; 

template <class I, class = void> 
    struct is_random_access: boost::false_type 
    {}; 

template <class I> 
    struct is_random_access<I,void_t<typename std::iterator_traits<I>::iterator_category> > 
     : boost::is_convertible 
     <typename boost::iterator_traversal<I>::type, boost::random_access_traversal_tag> 
    {}; 

Если тип входного сигнала не имеют iterator_category тип определен, он будет падать обратно структуры по умолчанию, если она определена, он будет использовать вашу специализацию.

Для второго вопроса я не эксперт. Однако моя интерпретация согласуется с вашим: для каждого итератора с std::random_access_iterator_tag, boost::iterator_traversal<>::type будет конвертирован в boost::random_access_traversal_tag.


Обновление: Исправлена ​​проблема, заключавшаяся в том, что int * не зарегистрирован как действительный итератор. Заменено I:iteratory_category на std::iterator_traits<I>::iterator_category.

+0

Спасибо, много, это довольно аккуратно. Я не знал о методе 'void_t <..>', и это очень полезно. К сожалению, это решение не совсем работает. Мы не можем использовать 'I :: iterator_category', так как мы хотим также, например, 'is_random_access ' будет действительным и быть правдой. Так что это должно быть 'boost :: iterator_traversal :: type', однако sfinae не работает так, как это (изменение на это, чтобы увидеть ошибку) – Nick

+0

Спасибо за обновленное сообщение. Для записи 'std :: iterator_traits :: iterator_category' действительно работает, а' boost :: iterator_traversal :: type' не является, что является довольно неясной вещью, видимо, о уже неясном шаблоне sfinae. – Nick

Смежные вопросы