More C++ Idioms/SFINAE

= SFINAE =

Intent
Prune functions that do not yield valid template instantiations from a set of overloaded functions.

Also Known As
Substitution Failure Is Not An Error

Motivation and Solution
Strictly, SFINAE is a language feature and not an idiom. However, this language feature is exploited in a very idiomatic fashion using enable-if.

In the process of template argument deduction, a C++ compiler attempts to instantiate signatures of a number of candidate overloaded functions to make sure that exactly one overloaded function is available as a perfect match for a given function call. If an invalid argument or return type is formed during the instantiation of a function template, the instantiation is removed from the overload resolution set instead of causing a compilation error. As long as there is one and only one function to which the call can be dispatched, the compiler issues no errors.

For example, consider, a simple function multiply and its templatized counterpart.

Calling function  in   causes the compiler to try instantiate the signature of the templatized function even though the first   function is a better match. During instantiation an invalid type is produced:. Due to SFINAE, however, this invalid instantiation is neglected automatically. At the end, there is exactly one  function that can be called, the first one. Thus the compilation is successful.

SFINAE is often exploited in determining properties of types at compile-time. For instance, consider the following  meta-function that determines at compile-time if the given type is a pointer of some sort.

The  meta-function above would not work without SFINAE. It defines 4 overloaded  functions, three of which are templates that accept one argument each: a pointer to a variable, pointer to a member variable, or a simple function pointer. All three functions return a, which is deliberate. The last  function is a catch-all function that uses ellipsis as it parameter. This function, however, returns a, which is always greater in size compared to a character.

When the  is passed a type that is really a pointer (e.g., IntPtr),   is initialized to true as a result of the comparison of two   expressions. The first  expression calls. If at all it is a pointer, only one of the overloaded template functions match and not others. Due to SFINAE, however, no error is raised because at least one function is found to be suitable. If none of the functions are suitable, the function with ellipsis is used instead. That function however, returns a, which is larger than a character and so the   is initialized to false as the comparison of   fails.

Note that, none of the  functions have definitions. Only declarations are sufficient to trigger SFINAE rule in the compiler. Those functions themselves must be templates, however. That is, a class template with regular functions will not participate in SFINAE. The functions that participate in SFINAE must be templates.

Known Uses

 * Member Detector

Related Idioms

 * enable-if