What is SFINAE in C++?
Can you please explain it in words understandable to a programmer who is not versed in C++? Also, what concept in a language like Python does
SFINAE is a principle a C++ compiler uses to filter out some templated function overloads during overload resolution (1)
When the compiler resolves a particular function call, it considers a set of available function and function template declarations to find out which one will be used. Basically, there are two mechanisms to do it. One can be described as syntactic. Given declarations:
template void f(T); //1
template void f(T*); //2
template void f(std::complex); //3
resolving f((int)1) will remove versions 2 and three, because int is not equal to complex or T* for some T. Similarly, f(std::complex would remove the second variant and f((int*)&x) would remove the third. The compiler does this by trying to deduce the template parameters from the function arguments. If deduction fails (as in T* against int), the overload is discarded.
The reason we want this is obvious - we may want to do slightly different things for different types (eg. an absolute value of a complex is computed by x*conj(x) and yields a real number, not a complex number, which is different from the computation for floats).
If you have done some declarative programming before, this mechanism is similar to (Haskell):
f Complex x y = ...
f _ = ...
The way C++ takes this further is that the deduction may fail even when the deduced types are OK, but back substitution into the other yield some "nonsensical" result (more on that later). For example:
template void f(T t, int(*)[sizeof(T)-sizeof(int)] = 0);
when deducing f('c') (we call with a single argument, because the second argument is implicit):
T against char which yields trivially T as charTs in the declaration as chars. This yields void f(char t, int(*)[sizeof(char)-sizeof(int)] = 0).int [sizeof(char)-sizeof(int)]. The size of this array may be eg. -3 (depending on your platform).<= 0 are invalid, so the compiler discards the overload. Substitution Failure Is Not An Error, the compiler won't reject the program.In the end, if more than one function overload remains, the compiler uses conversion sequences comparison and partial ordering of templates to select one that is the "best".
There are more such "nonsensical" results that work like this, they are enumerated in a list in the standard (C++03). In C++0x, the realm of SFINAE is extended to almost any type error.
I won't write an extensive list of SFINAE errors, but some of the most popular are:
typename T::type for T = int or T = A where A is a class without a nested type called type.int C::* for C = intThis mechanism is not similar to anything in other programming languages I know of. If you were to do a similar thing in Haskell, you'd use guards which are more powerful, but impossible in C++.
1: or partial template specializations when talking about class templates