Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template function that matches only certain types?

I want to define a function template:

template<typename T>
void foo(T arg)

But I want T to match only certain types. Specifically, T should derive (maybe through multiple inheritance) form a certain base class. Otherwise this template shouldn't be included in the overload set.

How can I do this?

like image 827
becko Avatar asked Jul 23 '15 19:07

becko


1 Answers

Use SFINAE with std::is_base_of:

template <typename T,
          typename = std::enable_if_t<
              std::is_base_of<Foo, T>::value
          >>
void foo(T arg);

That will only include foo in the overload set if T inherits from Foo. Note that this includes ambiguous and inaccessible bases as well. If you want a solution that only allows for Ts that inherit publicly and unambiguously from Foo, then you can instead use std::is_convertible:

template <typename T,
          typename = std::enable_if_t<
              std::is_convertible<T*, Foo*>::value
          >>
void foo(T arg);

Note the reversal of arguments.

Regardless of which form you pick, it can be aliased for brevity:

template <typename T>
using enable_if_foo = std::enable_if_t<std::is_base_of<Foo, T>::value>;

template <typename T,
          typename = enable_if_foo<T>>
void foo(T arg);

This works because std::enable_if has a nested type named type if and only if the boolean passed in is true. So if std::is_base_of<Foo, T>::value is true, enable_if_t gets instantiated to void, as if we had written:

template <typename T,
          typename = void>
void foo(T arg);

But, if T does not inherit from Foo, then the type trait will evaluate as false, and std::enable_if_t<false> is a substitution failure - there is no typename enable_if<false>::type. You might expect this to a compile error, but substitution failure is not an error (sfinae). It's just a template deduction failure. So the effect is that foo<T> is simply removed from the set of viable overload candidates in this case, no different from any other template deduction failure.

like image 134
Barry Avatar answered Sep 19 '22 07:09

Barry