e_card
e_card

Reputation: 119

C++ specialize single method in template class

I have the situation that I have an existing template class which works fine for all kind of datatypes. But now I need to specialize it for classes which derive from a specific class. But not the whole class should be specialized but only some functions.

I tried to do it like it is described in this post.

class BaseClass
{
   public:

   bool DoSomething()
   {
       return true;
   }
};

class SubClass : BaseClass
{
};

template<typename T, typename _Alloc = std::allocator<T>>
class TemplateClass
{
   public:
    template<typename U = T, typename std::enable_if<
       !std::is_base_of<BaseClass, U>::value>::type>
    void print_line()
    {
       std::cout << "Parameter of general Type T" << std::endl;
    }

    template<typename U = T, typename std::enable_if<
       std::is_base_of<BaseClass, U>::value>::type>
    void print_line()
    {
       std::cout << "Parameter of specific Type BaseClass" << std::endl;
    }
};

I try to use the template like this:

TemplateClass<BaseClass>* tc1 = new TemplateClass<BaseClass>();
tc1->print_line();

TemplateClass<SubClass>* tc2 = new TemplateClass<SubClass>();
tc2->print_line();

TemplateClass<int>* tc3 = new TemplateClass<int>();
tc3->print_line();

For each function call i get the error there was no fitting method found. Another point is that in this article they say that enable_if shouldn't be used to select between implementations.

Does anyone has an idea what my mistake is or how to do this correctly? Thanks in advance!

Upvotes: 1

Views: 258

Answers (1)

nh_
nh_

Reputation: 2241

You can either change it to

template<typename U = T, typename std::enable_if<
   !std::is_base_of<BaseClass, U>::value>::type* = nullptr>
void print_line()
{
   std::cout << "Parameter of general Type T" << std::endl;
}

or

template<typename U = T>
typename std::enable_if<!std::is_base_of<BaseClass, U>::value, void>::type print_line()
{
   std::cout << "Parameter of general Type T" << std::endl;
}

and the other one accordingly.

The idea behind both is to produce an error for one of the methods during the instantiation of the function templates. Due to the error, the corresponding method is not considered during overload resolution such that there is only one method (the one that did not produce the error) available, which will then be called. std::enable_if is used to produce this error, because if its first parameter is false it does not define a type member so the function template cannot be instantiated and will be removed from overloading resolution.

Search for SFINAE for more detailed information.

Upvotes: 1

Related Questions