2016-12-01 68 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版的http://coliru.stacked-crooked.com/a/461c077a5cb8fcbc对我来说效果很好:输出'true'。 – AnT

+2

另外,两次重复的true_type似乎是一个错字。 – Eugene

+1

为什么不使用这个简单的代码'std :: is_convertible :: iterator_category,std :: input_iterator_tag>'。它会在您忘记输入名称时发出警告 – Danh

回答

1

您错过了typename

缺乏一个typename使得当替补T

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 
>; 

失败。默认情况下,iterator_traits<T>::iterator_category被假定为一个值。对于您的特定T,这是一种类型(所有T都是如此)。这似乎被您的编译器视为替换错误(我不确定您的编译器是否正确)。

一旦is_pure_input_iterator被替换失败排除,则选择其他超载,即false_type

iterator_traits<T>::iterator_category之前添加typename解决了您的问题,因为@ AnT2注意到here


作为is_convertible_v需要一个类型作为其第一个参数,无论Titerator_traits<T>::iterator_category只能是一个值,你可以is_pure_input_iterator可证明有没有T,使得它没有此故障。要么有一个规则来检测这个,并生成一个诊断(你的编译器不会发出),你的程序是不合格的,因为它没有诊断要求。

相关问题