Template specialization and inheritance

17,194

Solution 1

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.

Solution 2

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.

Solution 3

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.

Share:
17,194
Amadeus
Author by

Amadeus

Updated on June 07, 2022

Comments

  • Amadeus
    Amadeus about 2 years

    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()