I have been using (and seen used) static_assert
to flag undesired values of template parameter values. However, for all cases I came across it seems better and more elegant to disable those undesired values via SFINAE. For example
template<typename T,
class = std::enable_if<std::is_floating_point<T>::value>::type>
struct Foo { ... };
instead of
template<typename T>
struct Foo {
static_assert(std::is_floating_point<T>::value,
"Foo<T>: T must be floating point :-(");
...
};
So my question: when to use static_assert
instead of SFINAE and why?
EDIT
I think what I've learned so far is the following
1 SFINAE is a versatile and powerful but potentially very complicated tool that can be used for many tasks, including function overload resolution (which some seem to regard as its only purpose).
2 SFINAE can be used in a relatively simple way where ever static_assert
can, except that it appears in the declaration (of a class or function) rather than its definition (or is is possible to insert a static_assert
into, say, a class forward declaration?). That makes more verbatim and hence clearer code. However, because SFINAE is complicated, it tends to be harder to get right than a simple static_assert
.
3 On the other hand static_assert
has the benefit of a clearer compiler error message, which some seem to regard as the main purpose of either.
static_assert
makes the compilation fail. SFINAE allows you to remove one possible overload.For one, using SFINAE may lead to another overload being picked that was originally a worse match and wouldn't be considered.
And in the situation that there are other overloads, but non of them is viable, you get some nice things like this:
Output:
You use SFINAE, if you want another overload to be used, and
static_assert
if none of them would fit such parameter.I think
static_assert
is the right choice if you want to enforce thatT
is a floating point type. This method states your intent more clearly than the SFINAE solution.