# How to Make SFINAE Pretty – Part 2: the Hidden Beauty of SFINAE

Before we start again, have you sent in yet your most beautiful piece of code that prints 42? Towel day is coming up, so join in the celebration!!

Now that is said again, we can start 🙂

As we’ve seen in How to Make SFINAE Pretty – Part 1: What SFINAE Brings to Code, SFINAE in code is as pretty as a windmill in a field. That is, not very pretty.

But like a windmill, it’s useful. SFINAE helps deactivate a piece of template code depending on a condition, and that can be very convenient.

For instance, our motivating example was to remove the second overload of this class template, in the case where `T`

is a reference (because in that case, it prevent the class from compiling):

1 2 3 4 5 6 7 |
template<typename T> class MyClass { public: void f(T const& x){} void f(T&& x){} }; |

And we ended up with an expression that works, but whose appearance is a slight to those who love to look at beautiful code:

1 2 3 4 5 6 7 8 9 10 11 |
template<typename T> class MyClass { public: void f(T const& x){} template<typename T_ = T> void f(T&& x, typename std::enable_if<!std::is_reference<T_>::value, std::nullptr_t>::type = nullptr){} }; |

If you’re not sure about how this works exactly, have a look at Part 1.

Now let’s put some makeup over that poor expression, to make it look presentable in our code.

To do this, we’ll use amongst others some techniques that Stephen Dewhurst has presented in his talk Modern C++ Interfaces.

This post is part on the series on SFINAE:

- How to make SFINAE pretty – Part 1: what value SFINAE brings to code
- How to make SFINAE pretty – Part 2: the hidden beauty of SFINAE

### *_t, *_v and {}

One of the burdens of the SFINAE expression is all the little things such as `::type`

, `typename`

and `::value`

that don’t add any meaning to the expression, but are there for technical reasons. Let’s see how to get rid of them.

#### *_t

C++14 adds a variation of `std::enable_if`

: `std::enable_if_t`

. It is just an alias for accessing the `::type`

inside `std::enable_if`

. Its implementation is this:

1 2 |
template< bool Condition, typename T = void > using enable_if_t = typename std::enable_if<Condition, T>::type; |

Since it is based on template aliases, this implementation is also compliant with C++11. So if you’re not in C++14 but in C++11 only, you can just an implementation like the one above.

`std::enable_if_t`

allows for a shorter syntax:

1 |
enable_if_t<a_certain_condition, MyType> |

as opposed to:

1 |
typename enable_if<a_certain_condition, MyType>::type |

In fact, the other template classes that have a `::type`

in the standard library also get a `_t`

counterpart in C++14. This includes `std::decay_t`

and `std::conditional_t`

for example.

#### *_v

In a similar way, the templates that contain a `::value`

, such as `std::is_reference`

or `std::is_const`

, get a `*_v`

counterpart in C++17.

Their implementation looks like this:

1 2 |
template<typename T> inline constexpr bool is_reference_v = is_reference<T>::value; |

This uses both a feature of C++14 (variable templates) and of C++17 (inline variables).

By using these features (depending on which version of C++ you have at hand), our SFINAE expression can be reduced from this:

1 |
typename std::enable_if<!std::is_reference<T_>::value, std::nullptr_t>::type = nullptr; |

down to this:

1 |
std::enable_if_t<!std::is_reference_v<T_>, std::nullptr_t> = nullptr; |

#### {}

If you have C++11 (and not C++14 or C++17), you can still shorten the `is_reference`

bit of the expression, by instantiating it with braces `{}`

inside the template call:

1 |
std::enable_if_t<!std::is_reference<T_>{}, std::nullptr_t> = nullptr; |

The bit we focus on here is this:

1 |
std::is_reference<T_>{} |

This instantiates a value of type `std::is_reference<T_>`

, which inherits from `std::true_type`

(respectively to `std::false_type`

, depending on whether `T_`

is a reference or not). And `std::true_type`

(resp. `std::false_type`

) is implicitly convertible to `bool`

, giving out the value `true`

(resp. `false`

). Thanks to Vittorio Romeo that took the time to explain this to me on his website.

### A place where SFINAE won’t get in the way

Here is an idea that Stephen Dewhurst has presented in one of his inspiring talks at CppCon: Modern C++ Interfaces. This talks contains lots of insights and changed my way of coding template interfaces. I recommend that you watch it.

C++11 introduced **default template parameters** for functions (and class methods) templates. Indeed, in C++98, only class templates could have default values for template types:

1 2 3 4 5 |
template<typename T = int> class MyClass { // ... }; |

And in C++11 we can also write:

1 2 3 4 5 |
template<typename T = int> void myFunction() { // ... } |

In fact, if we don’t use this parameter in the body of the function, we can even omit its name:

1 2 3 4 5 |
template<typename = int> void myFunction() { // ... } |

What would be the point of such a template parameter that we can’t use?

Well, it can host our SFINAE expression! Indeed, since we can put any type in a template parameter, including `void`

, we don’t have to resort to finding a dummy type like `nullptr_t`

for resolving the SFINAE. Conveniently enough, `std::enable_if`

has a default value for its underlying type, which is `void`

.

So our SFINAE expression is now reduced from this:

1 |
std::enable_if_t<!std::is_reference_v<T_>, std::nullptr_t> = nullptr; |

to this:

1 |
std::enable_if_t<!std::is_reference_v<T_>> |

And its position in the overload would be this:

1 2 3 4 5 6 7 8 9 |
template<typename T> class MyClass { public: void f(T const& x){} template<typename T_ = T, typename = std::enable_if_t<!std::is_reference_v<T_>>> void f(T&& x){} }; |

### Encapsulating the technical machinery

We could arguably stop here, but there is still a layer of template machinery that we could remove from this interface. In his talk, Stephen Dewhurst advises to hide the `enable_if`

expression behind a names that sums up its intent.

In our case here, such a name could be `EnableIfIsNotReference`

, or perhaps just `IsNotReference`

.

So let’s define an alias for the SFINAE expression that encapsulates it behind that name:

1 2 |
template<typename T> using IsNotReference = std::enable_if_t<!std::is_reference_v<T>>; |

Putting it all together, our code has now become:

1 2 3 4 5 6 7 8 9 10 11 12 |
template<typename T> using IsNotReference = std::enable_if_t<!std::is_reference_v<T>>; template<typename T> class MyClass { public: void f(T const& x){} template<typename T_ = T, typename = IsNotReference <T_>> void f(T&& x){} }; |

As a comparison, here is what we started with:

1 2 3 4 5 6 7 8 9 10 11 |
template<typename T> class MyClass { public: void MyClass(T const& x){} template<typename T_ = T> void f(T&& x, typename std::enable_if<!std::is_reference<T_>::value, std::nullptr_t>::type = nullptr){} }; |

It was worth the transformation, wasn’t it? This is pretty much exactly a commit I’ve made in the NamedType library after watching Modern C++ Interfaces.

There are other ways to make other situations of SFINAE clearer, such as C++17’s `if_constexpr`

inside a block of template code. But for an template interface, the above techniques are quite useful.

Related articles:

Become a Patron!Share this post! Don't want to miss out ?

**Follow:**