替换失败时,std::enable_if出现编译器错误



在下面的代码示例中,第二行

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,然后Tdouble替换时,std::enable_if_t<std::is_integral_v<T>>内部的条件评估为false。因此,此函数模板被忽略,此时不会产生任何错误。也就是说,你得到的错误不是由于SFINAESFINAE并不意味着您的程序不会产生任何错误

现在,为了使调用表达式is_even(4.4)工作,编译器找不到任何采用doubleis_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的函数。

最新更新