Question

I've looked around and not found quite what I'm looking for. Basically I want a function template specialized by a base class. I don't know how to make it use the specialized function.

Meaning...

class IBase
{
public:
    virtual std::string func() const = 0;
};

class MyClass : public IBase
{
public:
    std::string func() const { return "From MyClass"; }
};

template <class T>
std::string get_func(const T* t)
{
    return "Unknown";
}

template <>
std::string get_func<IBase>(const IBase* t)
{
    return t->func();
}

int main()
{
    int a;
    MyClass b;

    get_func(&a); // <- Returns 'Unknown'. Good.
    get_func(&b); // <- Returns 'Unknown'. Bad, want 'From MyClass'.
}

The reason I use const T* is because IBase is abstract.

Was it helpful?

Solution

Just use an overloaded function instead.

std::string get_func(const IBase *t) {
    return t->func();
}

Overloaded functions are always selected before templates.

OTHER TIPS

Using function overloads in the accepted answer to replace function template specialization isn't always a good idea. For the example code in the question, function overloading cannot provide a default implementation which prints "Unknown" for non-specialized classes. Other examples where function overloading is insufficient include tuples and virtually any variadic programming.

The primary reason why the code in question doesn't work is that currently, type deduction and conversion do not play nicely with each other. You need to cast &b to a pointer type to its parent class (i.e. IBase*) which the specialized function expects. Because of this issue in current C++, it's necessary to help out the compiler by using.

get_func((const IBase*)&b);

secondly, it may be better to add virtual to

std::string func() const { return "From MyClass"; } 

,since IBase::func is defined as a virtual member function. (This isn't necessary for all compilers: C++ "virtual" keyword for functions in derived classes. Is it necessary?).

With these changes, code below outputs what's expected:

Unknown
From MyClass

Code:

#include <string>
#include <iostream>
using namespace std;

class IBase
{
public:
    virtual std::string func() const = 0;
};

class MyClass : public IBase
{
public:
    virtual std::string func() const { return "From MyClass"; }
};

template <class T>
std::string get_func(const T* t)
{
    return "Unknown";
}

template <>
std::string get_func<IBase>(const IBase* t)
{
    return t->func();
}

int main()
{
    int a;
    MyClass b;

    cout << get_func(&a) << endl; // <- Returns 'Unknown'. Good.
    cout << get_func((const IBase*)&b) << endl; // 
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top