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

c++11 enable_if error - template parameter re-declaration


I am trying to get the following code to compile:

template <class T, typename std::enable_if<!std::is_fundamental<T>::value, int >::type = 0 >
class Calc
{
  public:
    int operator()( const T& v ) const {
        return v.getValue();
    }
};

template <class T, typename std::enable_if<std::is_fundamental<T>::value, int >::type = 0 >
class Calc : CalcBase <T>
{
};

On compilation I am getting the following error:

c.cpp:26: error: template parameter 'typename std::enable_if<(! std::is_fundamental::value), int>::type <anonymous>'
c.cpp:36: error: redeclared here as 'typename std::enable_if<std::is_fundamental::value, int>::type <anonymous>'

The intent here is to select the the version of Calc that overrides the base class function call operator if the passed template parameter is a class. If the passed parameter is a fundamental type, then we choose the version of Calc that does not override the base class functionality. Could you please help me understand how I can get this working?


Solution

  • I don't think class template declarations work with SFINAE: a class template isn't overloaded like a function template. You are declaring two primary class templates with the same name which isn't allowed.

    Conveniently, SFINAE isn't necessary for your use-case: class templates support partial specialization. You'd simply use a defaulted bool parameter and specialize the class template on whether the trait is true or false. For example:

    template <class T, bool = std::is_fundamental<T>::value>
    class Calc
    {
      public:
        int operator()( const T& v ) const {
            return v.getValue();
        }
    };
    
    template <class T>
    class Calc<T, false> : CalcBase <T>
    {
    };