Aleix Rius
Aleix Rius

Reputation: 84

std::enable_if to choose a class specialitzation

I'm tyring to understand std::enable_if and the benefits of using it over a static_assert / regular template specialitzation.

After reading around I found:

This is useful to hide signatures on compile time when a particular condition is not met, since in this case, the member enable_if::type will not be defined and attempting to compile using it should fail. http://www.cplusplus.com/reference/type_traits/enable_if/

My question then is: Why the compiler blames me by saying that class C is already declared?, when only one of the declaraions should be avaiable at a time.

class Interface{};

class Foo : public Interface{};

template <class T, typename = typename std::enable_if<std::is_base_of<Interface,T>::value>::type>
class C{
   // Some custom implementation
}

template <class T, typename = typename std::enable_if<!std::is_base_of<Interface,T>::value>::type>
class C { 
  //Some fallback / default implementation
}

int main() {
    C<Foo> myVariable;
}

Same behaviour in Godbolt: https://godbolt.org/z/cbfhG9q54

Thanks in advance!

Upvotes: 2

Views: 1049

Answers (1)

dfrib
dfrib

Reputation: 73236

You cannot overload class templates like you can function templates, buy you can partially specialize them (which you cannot do with function templates):

#include <ios>
#include <iostream>
#include <type_traits>

class Interface
{};
class Foo : public Interface
{};

template <class T, typename = void>
struct C
{
    // Some default impl.
    static constexpr bool is_default_impl{true};
};

template <class T>
struct C<T, std::enable_if_t<std::is_base_of_v<Interface, T>>>
{
    // Some custom implementation.
    static constexpr bool is_default_impl{false};
};

int main()
{
    std::cout << std::boolalpha 
        << C<int>::is_default_impl << " "  // true
        << C<Foo>::is_default_impl;        // false
}

Note that this examples requires C++17 for the variable template std::is_base_of_v which is a short-hand constant the value member of the std::is_base_of trait, and C++14 for the alias template std::enable_if_t, which aliases the type member alias declaration of the std::enable_if trait.

Upvotes: 4

Related Questions