C++ Idioms
http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms:
enable_if implementation:
=== Solution and Sample code===
The enable_if templates are very simple syntactically. They always come in pairs: one of them is empty and the other one has a <code>type</code> typedef that forwards its second type parameter. The empty structure triggers an invalid type because it contains no member. When a compile-time condition is false, the empty <code>enable_if</code> template is chosen. Appending <code>::type</code> would result in an invalid instantiation, which the compiler throws away due to the SFINAE principle.
<source lang="cpp">
template <bool, class T = void>
struct enable_if
{};
template <class T>
struct enable_if<true, T>
{
typedef T type;
};
</source>
Here is an example that shows how an overloaded template function can be selected at compile-time based on arbitrary properties of the type parameter. Imagine that the function '''T foo(T t)''' is defined for all types such that T is arithmetic. The enable_if template can be used either as the return type, as in this example:
<source lang="cpp">
template <class T>
typename enable_if<is_arithmetic<T>::value, T>::type
foo(T t)
{
// ...
return t;
}
</source>
or as an extra argument, as in the following:
<source lang="cpp">
template <class T>
T foo(T t, typename enable_if<is_arithmetic<T>::value >::type* dummy = 0);
</source>
The extra argument added to foo() is given a default value. Since the caller of foo() will ignore this dummy argument, it can be given any type. In particular, we can allow it to be void *. With this in mind, we can simply omit the second template argument to '''enable_if''', which means that the '''enable_if<...>::type''' expression will evaluate to ''void'' when '''is_arithmetic<T>''' is true.
Whether to write the enabler as an argument or within the return type is largely a matter of taste, but for certain functions, only one alternative is possible:
* Operators have a fixed number of arguments, thus '''enable_if''' must be used in the return type.
* Constructors and destructors do not have a return type; an extra argument is the only option.
* There does not seem to be a way to specify an enabler for a conversion operator. Converting constructors, however, can have enablers as extra default arguments.