我已经使用过 SFINAE 习语很多次了,而且我习惯了把我的std::enable_if<>
在模板参数中而不是在返回类型中。然而,我遇到了一些微不足道的情况,它不起作用,我不知道为什么。首先,这是我的主要内容:
int main()
{
foo(5);
foo(3.4);
}
这是一个实现foo
触发错误:
template<typename T,
typename = typename std::enable_if<std::is_integral<T>::value>::type>
auto foo(T)
-> void
{
std::cout << "I'm an integer!\n";
}
template<typename T,
typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
auto foo(T)
-> void
{
std::cout << "I'm a floating point number!\n";
}
这是一段据称等效的代码,可以正常工作:
template<typename T>
auto foo(T)
-> typename std::enable_if<std::is_integral<T>::value>::type
{
std::cout << "I'm an integrer!\n";
}
template<typename T>
auto foo(T)
-> typename std::enable_if<std::is_floating_point<T>::value>::type
{
std::cout << "I'm a floating point number!\n";
}
我的问题是:为什么第一次执行foo
触发该错误而第二个错误不触发它?
main.cpp:14:6: error: redefinition of 'template<class T, class> void foo(T)'
auto foo(T)
^
main.cpp:6:6: note: 'template<class T, class> void foo(T)' previously declared here
auto foo(T)
^
main.cpp: In function 'int main()':
main.cpp:23:12: error: no matching function for call to 'foo(double)'
foo(3.4);
^
main.cpp:6:6: note: candidate: template<class T, class> void foo(T)
auto foo(T)
^
main.cpp:6:6: note: template argument deduction/substitution failed:
main.cpp:5:10: error: no type named 'type' in 'struct std::enable_if<false, void>'
typename = typename std::enable_if<std::is_integral<T>::value>::type>
^
EDIT :
工作代码 http://coliru.stacked-crooked.com/a/69673770917ff0e6 and 有错误的代码 http://coliru.stacked-crooked.com/a/e43f8c05fecb9b50.
你应该看看14.5.6.1 Function template overloading
(C++11 标准)其中定义了函数模板等效性。简而言之,不考虑默认模板参数,因此在第一种情况下,您定义了两次相同的函数模板。在第二种情况下,您有引用返回类型中使用的模板参数的表达式(再次参见 14.5.6.1/4)。由于此表达式是签名的一部分,因此您将获得两个不同的函数模板声明,因此 SFINAE 有机会工作。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)