Template class methods definition with enable_if as template parameter

Here's how SFINAE can actually work with partial specialization:

template<typename T, typename Sfinae = void>
struct Foo {
    /* catch-all primary template */
    /* or e.g. leave undefined if you don't need it */
};

template<typename T>
struct Foo<T, typename std::enable_if<std::is_base_of<BasePolicy, T>::value>::type> {
    /* matches types derived from BasePolicy */
    Foo();
};

The definition for that constructor can then be awkwardly introduced with:

template<typename T>
Foo<T, typename std::enable_if<std::is_base_of<BasePolicy, T>::value>::type>::Foo()
{
    /* Phew, we're there */
}

If your compiler supports template aliases (it's a C++11 feature) that then you can cut a lot of the verbosity:

template<typename T>
using EnableIfPolicy = typename std::enable_if<std::is_base_of<BasePolicy, T>::value>::type;

// Somewhat nicer:

template<typename T>
struct Foo<T, EnableIfPolicy<T>> {
    Foo();
};

template<typename T>
Foo<T, EnableIfPolicy<T>>::Foo() {}

Note: your original answer referred to utilies from Boost, like boost::enable_if_c and boost::is_base_of. If you're using that instead of std::enable_if and std::is_base_of (which are from C++11), then usage looks like

typename boost::enable_if<boost::is_case_of<BasePolicy, T> >::type

which has the advantage of getting rid of one ::value.


From the looks of it, you want to do something along the lines of this:

template <typename Policy,
          typename = typename std::enable_if<std::is_base_of<BasePolicy, Policy>::value>::type >
struct Foo;

template <typename Policy>
struct Foo<Policy> {
    Foo();
};

template <typename Policy>
Foo<Policy>::Foo() {
}

This sneakily takes advantage of the default argument in a few places: don't get confused, there is an implicit void sitting in several locations.

Tags:

C++

Templates