I already used the SFINAE idiom quite a few times and I got used to put my std::enable_if<>
in template parameters rather than in return types. However, I came across some trivial case where it didn't work, and I'm not sure why. First of all, here is my main:
int main()
{
foo(5);
foo(3.4);
}
Here is an implementation of foo
that triggers the error:
template<typename T,
typename = typename std::enable_if<std::is_integral<T>::value>::type>
auto foo(T)
-> void
{
std::cout << "I'm an integer!
";
}
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!
";
}
And here is a supposedly equivalent piece of code that works fine:
template<typename T>
auto foo(T)
-> typename std::enable_if<std::is_integral<T>::value>::type
{
std::cout << "I'm an integrer!
";
}
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!
";
}
My question is: why does the first implementation of foo
triggers that error while the second one does not trigger it?
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 :
Working code and faulty code.
question from:
https://stackoverflow.com/questions/15427667/sfinae-working-in-return-type-but-not-as-template-parameter 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…