I have this simple code:
class A{};
class B : public A{};
class C : public B{};
class Test
{
public:
template<typename T>
void f(T&){printf("template\n");}
void f(A&){printf("specialization\n");}
};
int main()
{
A a;
B b;
C c;
Test test;
test.f(a);
test.f(b);
test.f(c);
}
When I run it(VS2010) I have this output:
specialization
template
template
Is it possible to make the calls with A-derived classes to use specialization?
Yes, it is possible, but you have to change your code a bit.
First of all, to be technical, the second function
f()is not a specialization of the template function, but an overload. When resolving overload, the template version is chosen for all arguments whose type is notA, because it is a perfect match:Tis deduced to be equal to the type of the argument, so when callingf(b), for instance, after type deduction the compiler will have to choose between the following two overloads:Of course, the first one is a better match.
Now if you want the second version to be selected when the function is invoked with an argument which is a subclass of
A, you have to use some SFINAE technique to prevent the function template from being correctly instantiated when the typeTis deduced to be a subclass ofA.You can use
std::enable_ifin combination with thestd::is_base_oftype traits to achieve that.Here is how you would use it in a complete program:
EDIT:
If you are working with a compiler which is not fully compliant with C++11 (and therefore does not support default template arguments on function templates), you might want to change the definition of your template overload of
f()as follows:The behavior of the program will be identical. Note that if the return type of
f()isvoid, you can omit the second argument to theenable_ifclass template.