2016-12-01 9 views
2
#include <iostream> 
#include <type_traits> 

using namespace std; 

template<typename T> 
constexpr auto is_pure_input_iterator(int) -> 
conditional_t 
< 
    is_convertible_v 
    < 
    iterator_traits<T>::iterator_category, 
    input_iterator_tag 
    >, 
    true_type, false_type 
>; 

template<typename> 
constexpr false_type is_pure_input_iterator(...); 

int main() 
{ 
    cout << boolalpha 
     << decltype(is_pure_input_iterator<istream_iterator<int>>(0))::value 
     << endl; 

    return {}; 
} 

Ожидаемый результат должен быть: true, но актуальным является false.Почему SFINAE работает не так, как ожидалось в этом примере?

Что не так в моем коде?

+1

Должно быть 'typename iterator_traits :: iterator_category'. В противном случае эта версия C++ 14-ed http://coliru.stacked-crooked.com/a/461c077a5cb8fcbc отлично подходит для меня: выводит «истина». – AnT

+2

Кроме того, true_type, повторяемый дважды, кажется опечаткой. – Eugene

+1

Почему вы не используете этот простой код 'std :: is_convertible :: iterator_category, std :: input_iterator_tag>'. Это даст предупреждение, когда вы забыли имя_файла – Danh

ответ

1

Вам не хватает typename.

Отсутствие typename делает

template<typename T> 
constexpr auto is_pure_input_iterator(int) -> 
conditional_t 
< 
    is_convertible_v 
    < 
    iterator_traits<T>::iterator_category, 
    input_iterator_tag 
    >, 
    true_type, false_type 
>; 

терпят неудачу, когда вы заменяете T. По умолчанию, iterator_traits<T>::iterator_category считается значение. Для вашего конкретного T это тип (что верно для всех T). Это, по-видимому, рассматривается как ошибка замещения вашим компилятором (я не уверен, что ваш компилятор верен).

После того, как is_pure_input_iterator исключен из-за отказа замещения, выбрана другая перегрузка, которая равна false_type.

Добавление typename до исправляет вашу проблему, так как @ AnT2 заметил here.


Как is_convertible_v требует типа в качестве первого аргумента, и независимо от Titerator_traits<T>::iterator_category может быть только значение, ваш is_pure_input_iterator может доказуемо не имеют T таким образом, что он не имеет такой провал. Либо есть правило, чтобы обнаружить это, так и сгенерировать диагностику (которую ваш компилятор не испускает), или ваша программа плохо сформирована, поэтому из-за нее не требуется диагностика.