为什么 SFINAE 在这个例子中没有按预期工作?
Why does SFINAE not work as expected in this example?
#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
。
我的代码有什么问题?
您缺少 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
都是如此)。这似乎被您的编译器视为替换错误(我不确定您的编译器是否正确1)。
一旦 is_pure_input_iterator
被替换失败排除,则选择另一个重载,即 false_type
。
在 iterator_traits<T>::iterator_category
之前添加 typename
可以解决您的问题,正如@AnT2 注意到的 here.
1 因为 is_convertible_v
需要一个类型作为它的第一个参数,并且不管 T
iterator_traits<T>::iterator_category
只能是一个值,你的is_pure_input_iterator
可以证明没有 T
这样它就没有这个失败。要么有一个规则来检测这个并生成一个诊断(你的编译器不会发出),要么你的程序格式错误,因此不需要诊断。
#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
。
我的代码有什么问题?
您缺少 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
都是如此)。这似乎被您的编译器视为替换错误(我不确定您的编译器是否正确1)。
一旦 is_pure_input_iterator
被替换失败排除,则选择另一个重载,即 false_type
。
在 iterator_traits<T>::iterator_category
之前添加 typename
可以解决您的问题,正如@AnT2 注意到的 here.
1 因为 is_convertible_v
需要一个类型作为它的第一个参数,并且不管 T
iterator_traits<T>::iterator_category
只能是一个值,你的is_pure_input_iterator
可以证明没有 T
这样它就没有这个失败。要么有一个规则来检测这个并生成一个诊断(你的编译器不会发出),要么你的程序格式错误,因此不需要诊断。