Search code examples
c++templatesc++11sfinaeenable-if

how to use enable_if with overloads


enum class enabler{};

template<typename T> 
class X {
   template<typename std::enable_if<std::is_class<T>::value,enabler>::type = enabler()>
    void func();
    void func(int a);
    void func(std::string b);
};

I have this class with these 3 overloads for func. I need the second/third versions to be available for both class/non-class types, and the first version to be available only for class types. when I tried to use enable_if as above, the class instantiation for non-class types gives compile error.


Solution

  • For SFINAE to work, the template argument must be deduced. In your case, T is already known by the time you attempt to instantiate func, so if the enable_if condition is false, instead of SFINAE, you get a hard error.

    To fix the error, just add a template parameter whose default value is T, and use this new parameter in the enable_if check. Now deduction occurs and SFINAE can kick in for non-class types.

    template<typename U = T,
             typename std::enable_if<std::is_class<U>::value,enabler>::type = enabler()>
    void func();
    

    And you don't really need a dedicated enabler type either, this works too

    template<typename U = T,
             typename std::enable_if<std::is_class<U>::value, int>::type* = nullptr>
    void func();