33
votes

Suppose I have a template class with a lot of functions and I want to specialize them to change only a few of them and keep the other ones exactly as specified in the base template class.

How can I do that?

Below is what I want to achieve, but the solution isn't good, because it does not allow me to refer to the specialization for int as Base<int> – I need to use IntSpec for that.

#include <iostream>

using namespace std;

template<typename T>
struct Base
{
  void print1() {cout << "Base::print1" << endl;};
  void print2() {cout << "Base::print2" << endl;};
};

struct IntSpec : public Base<int>
{
  void print2() {cout << "Base<int>::print2()" << endl;};
};

int main()
{
  Base<double> d;
  // Base<int> i;  <-- I want this kind of instantiation
  IntSpec i;

  d.print1();
  d.print2();
  i.print1();
  i.print2();
}

The output is:

Base::print1
Base::print2
Base::print1
Base<int>::print2()
3

3 Answers

45
votes

Nicol's solution works fine, but this is an alternative:

template<typename T>
struct Base
{
  void print1() {cout << "Base::print1" << endl;};
  void print2() {cout << "Base::print2" << endl;};
};

template<>
void Base<int>::print2() {cout << "Base<int>::print2()" << endl;};

That way you can specialize only specific member functions and still use those that you haven't specialized(in this case, print1) without any problem. So now you'd use it just like you wanted:

Base<int> i;
i.print1();
i.print2(); // calls your specialization

Demo here.

26
votes

You just have to use two template classes:

template<typename T>
struct CommonBase
{
  void print1() {cout << "Base::print1" << endl;};
  void print2() {cout << "Base::print2" << endl;};
};

template<typename T>
struct Base : public CommonBase<T>
{
};

template<>
struct Base<int> : public CommonBase<int>
{
  void print2() {cout << "Base::print2" << endl;};
};

You always use Base, rather than CommonBase.

4
votes

Another solution would be to add a level of indirection in the function you want to redefine, i.e.

template<typename T>
struct foo
{
    template<typename T2>
    void bar_impl()
    {
        //generic function
    }

    void bar()
    {
        bar_impl<T>();
    }
};

Then you can specialize each function individually for each type or specialize the whole type as wanted.