3

I have a base class with a templated function that has the general templated type, as well as specialized version.

#ifndef BASE_CLASS
#define BASE_CLASS

#include <iostream>

using namespace std;

struct Type1
{
};

struct Type2
{
};

class baseClass
{
    public:
    template<class Type>
    void doStuff(Type & t)
        {
        templateFunction(t);  
        }

    template<class Type>
    void templateFunction(Type & t);
};

template<class Type>
void baseClass::templateFunction(Type & t)
{
    cout << "This is the generic function!" << endl;
}

template<>
void baseClass::templateFunction(Type1 & t)
{
    cout << "This is the specialized function: - Type1" << endl;
}
#endif

I also have a child class, that inherits from "baseClass". However, the child class requires different functionality for that specialization.

#ifndef CHILD_CLASS
#define CHILD_CLASS

#include "BaseClass.h"

class ChildClass : public baseClass
{
    public:

};

template<>
void ChildClass::templateFunction(Type1 & t)
{
    cout << "We overloaded the specialized template function for type 1!" << endl;
}

#endif

The above does not compile:

ChildClass.h:13: error: no member function âtemplateFunctionâ declared in âChildClassâ ChildClass.h:13: error: invalid function declaration

If I change the "overloaded" function to:

template<>
void baseClass::templateFunction(Type1 & t)
{
    cout << "We overloaded the specialized template function for type 1!" << endl;
}

I get: ChildClass.h:13: error: redefinition of âvoid baseClass::templateFunction(Type&) [with Type = Type1]â BaseClass.h:36: error: âvoid baseClass::templateFunction(Type&) [with Type = Type1]â previously declared here

How do I properly overload specialized template functions in child classes?

For reference, the main:

#include "BaseClass.h"
#include "ChildClass.h"

int main()
{
    Type1 first;
    Type2 second;

    baseClass theBaseClass;
    ChildClass theChildClass;


    theBaseClass.doStuff(first);
    theBaseClass.doStuff(second);

    theChildClass.doStuff(first);
    theChildClass.doStuff(second);

    return 0;
}

On the suggestion of: Kerrek SB, I've changed the ChildClass to:

#ifndef CHILD_CLASS
#define CHILD_CLASS

#include "BaseClass.h"
class ChildClass : public baseClass
{
    public:
    template<class Type>
    void templateFunction(Type & t);
};

template<>
void ChildClass::templateFunction(Type1 & t)
{
    cout << "We overloaded the specialized template function for type 1!" << endl;
}

#endif

The output:

This is the specialized function: - Type1
This is the generic function!
This is the specialized function: - Type1
This is the generic function!

I was hoping for:

This is the specialized function: - Type1
This is the generic function!
We overloaded the specialized template function for type 1!
This is the generic function!

So this still doesn't work.

Alex
  • 6,843
  • 10
  • 52
  • 71
  • 1
    Templated functions cannot be virtual, are you sure you mean to redefine the member function in the derived class while *hiding* the original function? You cannot get to the redefined function via pointer to base! If you're sure, you should add the non-specialized declaration to the derived class as well. – Kerrek SB Aug 11 '11 at 21:48
  • I don't need access to the baseClass' original specialized function, no. At least for any given instance of ChildClass. – Alex Aug 11 '11 at 21:53
  • 1
    Well, in that case I believe you should be able to do it if you add the primary template declaration of the function to the derived class before specializing it. – Kerrek SB Aug 11 '11 at 22:17
  • Re your edit: You've added overrides for `templateFunction`, but you're calling `doStuff` -- that cannot work. Override the function you're actually calling! How is a base class function supposed to know about a non-virtual override in a derived class? Why make your life so complicated, start with a simpler example... – Kerrek SB Aug 12 '11 at 07:56

2 Answers2

5

The reason why it still doesn't work the way you wanted to is that the function is not virtual in the parent class. However, it is not possible to have a virtual template function.

I see two main options:

  • as rhalbersma suggested, make the class itself template and then override the desired method s (which now are NOT template) in the child class.
  • for the specialized method, just write a new method, with a different name, that does whatever you need.

But I'm sure someone will come up with a better idea... =)

bartgol
  • 1,703
  • 2
  • 20
  • 30
2

You could make a template class with a virtual function like this:

template<typename T>
class B
{
    virtual void f() { std::cout << "base template implementation \n"; }
};

template<>
class B<Type1>
{
    virtual void f() { std::cout << "base specialized implementation \n"; }
};

template<typename T>
class D: public B<T>
{
    virtual void f() { std::cout << "derived template implementation \n"; }
};

template<>
class D<Type1>: public B<Type1>
{
    virtual void f() { std::cout << "derived specialized implementation \n"; }
};

B<Type1> b1;
B<Type2> b2;
D<Type1> d1;
D<Type2> d2;

b1.f();
b2.f();
d1.f();
d2.f();

Now there are 2 independent dimensions of customization: either the template T, or the dynamic type (B vs D). For each template instantiation, the virtual functions can be redefined.

More common is to let B be a regular class with pure virtual functions (i.e. an interface), and let D be a template class deriving from B. This lets you redefine the virtual functions of B in a different way for each template instantiation of D (with a suitable default).

TemplateRex
  • 69,038
  • 19
  • 164
  • 304