This rule applies during overload resolution of function
templates: When substituting the explicitly specified or deduced type for the template parameter fails, the
specialization is discarded from the overload set instead of causing a compile error.
Because the attempted substitution is not an error, SFINAE is used as alternative to concepts in compilers
that do not support C++20. The technique specifies the template parameters is such a way that only the intended
template types are instanciated.
1
#include<type_traits>
123456789
// The overload fails if the first parameter is not arithmetictemplate<classT>voidmax(std::enable_if_t<std::is_arithmetic_v<T>,T>a,Tb){if(a>b){std::cout<<"max: "<<a<<'\n';}else{std::cout<<"max: "<<b<<'\n';}}
123456
// The overload fails if the first parameter is arithmetictemplate<classT>voidmax(std::enable_if_t<!std::is_arithmetic_v<T>,T>a,Tb){std::cout<<"a: "<<a<<'\n';std::cout<<"b: "<<b<<'\n';}
12
max(5,7);// call overload for arithmetic typesmax("foo","bar");// call overload for non-arithmetic types
1234
// The return type (bool) is only valid if T is an integral type:template<classT>std::enable_if_t<std::is_integral_v<T>,bool>is_odd(Ti){returnbool(i%2);}
12345
// The second template argument is only valid if T is an integral typetemplate<classT,class=std::enable_if_t<std::is_integral_v<T>>>boolis_even(Ti){return!bool(i%2);}
123
std::cout<<"i is odd: "<<is_odd(1)<<'\n';// is_odd(1.2) wouldn't workstd::cout<<"i is even: "<<is_even(1)<<'\n';// is_even(1.2) wouldn't work