I was wondering about the advantage of std::enable_if
over static_asserts
to prevent template instantiation. This answer suggests, that std::enable_if
allows SFINAE, which is a convincing argument in the case of function templates.
However is this argument legitimate for class templates (and variable templates)? As far as I know, there is no overload resolution involved there, making SFINAE - again, as far as I know - not relevant, but I might be wrong. If so, can you name an example?
If not, I assume static_assert
to be the better solution for the given issue (preventing template instantiation) in the case of class templates, since it's arguably more explicit, concise and readable and allows a custom error message. Is that correct or am I missing a point other than SFINAE?
Handling a few distinct types can be done with specialising as you said:
template <class>
class foo;
template <>
class foo <int> { /* int implementation */ };
template <>
class foo <char> { /* char implementation */ };
Now consider that we want to specialise multiple types, and we want float
and double
to be in the same specialisation. We can't do this without SFINAE, so to avoid repeating the implementation we use inheritance:
class foo_fp_implementation {
/* specialise for all floating point */
};
template <>
class foo <float> : foo_fp_implementation {};
template <>
class foo <double> : foo_fp_implementation {};
So far we've avoided SFINAE, but what if you want a specialisation that takes all types with a certain interface? Example: has method int bar ()
? We could try to use the above trick and list all the possible types, but what if there are too many to maintain, or you want it to be usable by others who may use their own types. Here SFINAE comes to the rescue:
template <class, class = int>
class foo;
template <class T>
class foo <T, decltype(T().bar())> {
// implement using bar interface
};
// other specialisations...
In the above situation, static_assert
simply couldn't help.
In conclusion, SFINAE helps to specialise based off exact behaviour rather than exact types.
However is this argument legitimate for class templates (and variable templates)? As far as I know, there is no overload resolution involved there, making SFINAE - again, as far as I know - not relevant, but I might be wrong. If so, can you name an example?
You can specialise class templates and SFINAE may be used to pick between specialisations. It will also prevent instantiation of such (by then, possibly ill-formed) class / its specialisation, instead of failing to compile due to static_assert
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With