简体   繁体   中英

How do you overload templated function (specialized) in child class?

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.

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... =)

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM