Understanding SFINAE

c++, c++11, sfinae, template-argument-deduction, templates

Solution

In C++98, SFINAE is done with either a return type or a function's dummy argument with default parameter

// SFINAE on return type for functions with fixed arguments (e.g. operator overloading)
template<class T>
typename std::enable_if< std::is_integral<T>::value, void>::type
my_function(T const&);

// SFINAE on dummy argument with default parameter for functions with no return type (e.g. constructors)
template<class T>
void my_function(T const&, std::enable_if< std::is_integral<T>::value, void>::type* = nullptr);

In both cases, substution of `T` in order to get the nested type `type` is the essence of SFINAE. In contrast to `std::enable_if`, your `assert` template does not have a nested type that can be used in substitution part of SFINAE.

See Jonathan Wakely's excellent ACCU 2013 presentation for more details and also for the C++11 expression SFINAE. Among others (as pointed out by @BartekBanachewicz in the comments) is is now also possible to use SFINAE in function template default arguments

// use C++11 default function arguments, no clutter in function's signature!
template<class T, class dummy = typename std::enable_if< std::is_integral<T>::value, void>::type>
void my_function(T const&);

Problem

As far as I know, SFINAE means substitution failures do not result in compilation errors, but just remove the prototype from the list of possible overloads. What I do not understand: why is this SFINAE: ``` template <bool C, typename T = void> struct enable_if{}; template <typename T> struct enable_if<true, T> { typedef T type; }; ``` But this is not? ``` template <bool C> struct assert; template <> struct assert<true>{}; ``` From my understanding, the underlying logic is identical here. This question emerged from the comments to this answer.

Original source

Related problems