In C , SFINAE (Substitution Failure Is Not An Error) can be used to conditionally enable or disable template specializations based on type traits. However, a common issue arises when SFINAE is applied differently in template return types and template parameters.
Consider the following main function:
int main() { foo(5); foo(3.4); }
When SFINAE is placed in template parameters, as shown below, it fails to compile with an error:
template<typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type> auto foo(T) -> void { std::cout << "I'm an integrer!\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"; }
This implementation, however, works correctly:
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"; }
The difference lies in the way function template overloading is defined in the C standard (14.5.6.1). Overloaded templates are equivalent if they have the same function name, the same number of parameters, and the same parameter types. However, default template arguments are not considered in this comparison.
In the faulty implementation, the SFINAE condition is included as a default template argument, resulting in two identical function templates defined twice. This triggers the compilation error.
In the correct implementation, the SFINAE condition is used as part of the template return type. Since this involves expression referring template parameters, the two functions have different signatures and thus allow SFINAE to function as intended.
The above is the detailed content of SFINAE in C : Return Type vs. Parameter Type for Conditional Template Specialization?. For more information, please follow other related articles on the PHP Chinese website!