在下面的代码示例中,第二行
std::cout << "is_even (4.4) = " << std::boolalpha << is_even(4.4);
由于找不到正确的替换,导致编译器失败。如果有错误,那么这个SFINAE是怎么回事?我认为std::enable_if是一种SFINAE,缩写词意味着如果不能进行替换,就不会失败。我误解了什么?
#include <iostream>
#include <type_traits>
template<class T, class = std::enable_if_t<std::is_integral_v<T>>>
bool is_even(T value)
{
return ((value % 2) == 0);
}
int main()
{
std::cout << "is_even (4) = " << std::boolalpha << is_even(4);
std::cout << "is_even (4.4) = " << std::boolalpha << is_even(4.4);
}
请不要说我在这种情况下会发生什么。我只是想看看我该如何看待SFINAE?
错误是由调用表达式is_even(4.4)
引起的。由于通过传递double
调用了函数is_even
,因此必须存在此类函数的定义。
如果我们调用任何函数,那么它的定义一定存在于某个地方。在您的情况下,没有名为is_even
的函数接受double
参数,因此会出现错误。
SFINAE在这里仍然有效。例如,当模板自变量被推导为double
,然后T
被double
替换时,std::enable_if_t<std::is_integral_v<T>>
内部的条件评估为false
。因此,此函数模板被忽略,此时不会产生任何错误。也就是说,你得到的错误不是由于SFINAESFINAE并不意味着您的程序不会产生任何错误
现在,为了使调用表达式is_even(4.4)
工作,编译器找不到任何采用double
的is_even
。所以它产生了错误。您可以通过用如下所示的普通函数重载此函数模板来确认这一点:
template<class T, class = std::enable_if_t<std::is_integral_v<T>>>
bool is_even(T value)
{
return ((value % 2) == 0);
}
//compiler will find this definition now and no error will be produced
bool is_even(double d)
{
return ((static_cast<int>(d) % 2) == 0);
}
现在对于调用表达式is_even(4.4)
,编译器找到重载的is_even
,因此不会产生错误。
摘要
您得到的错误不是SFINAE的结果,而是由于表达式is_even(4.4)
要工作,我们需要定义一个使用double
的函数。