enforce iterator category
От: Lorenzo_LAMAS  
Дата: 22.06.15 07:11
Оценка:
братья, поделитесь "современным" ( в духе С++ 11/14) трюком —
мне надо в шаблонной функции ввести "ограничение" — категория итератора должна быть рэндом эксесс.
я сделал тупо:

........
template<class> struct invalid_iterator_category;
template<> struct invalid_iterator_category{};

template<class Iterator>
Iterator some_algorithm(Iterator first, Iterator last)
{
   using category = typename std::iterator_category<Iterator>::iterator_category;
   const invalid_iterator_category<category> dummy{};
   (void)dummy;
    .....
}


но, понятно, в современной библиотеке стандардной/в современном С++ должно быть что-то поудобнее. как это делается?
Of course, the code must be complete enough to compile and link.
Отредактировано 22.06.2015 7:18 Lorenzo_LAMAS . Предыдущая версия .
Re: enforce iterator category
От: andyp  
Дата: 22.06.15 07:35
Оценка: 8 (1)
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>братья, поделитесь "современным" ( в духе С++ 11/14) трюком -

L_L>мне надо в шаблонной функции ввести "ограничение" — категория итератора должна быть рэндом эксесс.


template<class Iterator>
typename std::enable_if<
    std::is_same<
    typename std::iterator_traits<Iterator>::iterator_category, 
    std::random_access_iterator_tag>::value, Iterator>::type
    some_algorithm(Iterator first, Iterator last)
{}


void test()
{
    std::vector<int> a;
    auto c = some_algorithm(a.begin(), a.end());
    int e;
    auto d = some_algorithm(&e, &e);
}
Re[2]: enforce iterator category
От: Lorenzo_LAMAS  
Дата: 22.06.15 07:53
Оценка:
Здравствуйте, andyp, Вы писали:

A>Здравствуйте, Lorenzo_LAMAS, Вы писали:


A>

A>template<class Iterator>
A>typename std::enable_if<
A>    std::is_same<
A>    typename std::iterator_traits<Iterator>::iterator_category, 
A>    std::random_access_iterator_tag>::value, Iterator>::type
A>    some_algorithm(Iterator first, Iterator last)
A>{}


отлично, диагностика компилятором выдается отменно читаемая!
Of course, the code must be complete enough to compile and link.
Re[3]: enforce iterator category
От: jazzer Россия Skype: enerjazzer
Дата: 22.06.15 08:18
Оценка: 4 (1)
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>отлично, диагностика компилятором выдается отменно читаемая!


http://rsdn.ru/forum/cpp/4533301.1
Автор: jazzer
Дата: 09.12.11
(читай вторую половину, которая "специальный совет")
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re: enforce iterator category
От: Кодт Россия  
Дата: 22.06.15 08:28
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>мне надо в шаблонной функции ввести "ограничение" — категория итератора должна быть рэндом эксесс.


Чтобы было random_access_iterator_tag, но никакой его субкласс "super_duper_iterator_tag"? (Не будет ли конфликтов с бустовскими итераторами?)

std::is_same или, что более подходит по смыслу, std::is_base_and_derived
Или по-старинке, 98
char ok_random_access_iterator(std::random_access_iterator_tag*);

template<class I> void algo(I begin, I end) {
  sizeof(ok_random_access_iterator( (typename std::iterator_traits<I>::iterator_category*)NULL ));
  ....
}

Аналогично можно и в SFINAE вытащить.
Перекуём баги на фичи!
Re[3]: enforce iterator category
От: jazzer Россия Skype: enerjazzer
Дата: 22.06.15 09:01
Оценка: 4 (1)
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>отлично, диагностика компилятором выдается отменно читаемая!


Собственно, у подхода с enable_if есть одна грабля, о которой частенько забывают: enable_if не отлавливает ошибки (и рапортует, если что не так), а просто выкидывает функцию из overload set по SFINAE.

Соответственно, может неожиданно сработать что-то еще, что и не предполагалось, но залетело в overload set по какому-нть using или ADL, не говоря уже о сообщении об ошибке, в котором будет лишь написано, что функция не найдена.
В то время как обычно нам хочется иметь внятное и короткое сообщение об ошибке и больше ничего.

Для этого достаточно просто дополнительно объявить функцию-перехватчик для всех неподходящих типов аргументов, которая не будет делать ничего, кроме рапорта об ошибке.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.