Reputation: 60702
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.
Upvotes: 0
Views: 1445
Reputation: 22560
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; //
}
Upvotes: 0
Reputation: 8734
Just use an overloaded function instead.
std::string get_func(const IBase *t) {
return t->func();
}
Overloaded functions are always selected before templates.
Upvotes: 1