I have created some code that uses a function template and an overload (not a specialization) of that function. When I call the function with an object of a class that is derived from the parameter in the it uses the template resulting in a compile error. I have been reading http://www.gotw.ca/publications/mill17.htm and I had the impression that overloaded functions would always have preference above templates. I have created a similar do-nothing example:
class ITest
{
public:
virtual void foo()=0;
};
class TheTest:public ITest
{
public:
virtual void foo()
{
}
};
class test
{
public:
template<typename T>
void handle(T par)
{
par++;
}
void handle(ITest &t)
{
t.foo();
}
};
void TestThem()
{
test t;
t.handle(2);
t.handle(3.0);
TheTest t2;
t.handle(t2);
}
I would expect t.handle(t2)
to call the overloaded void handle(ITest &t)
since TheTest
is derived from ITest
. However the compiler selects the template which generates an error.
When I change void handle(ITest &t)
to void handle(TheTest &t)
it compiles fine.
I fixed it by removing the template function and overloading for all used types, but this is cumbersome since they all do exactly the same thing.
I had the impression that overloaded functions would always have preference above templates.
This is true, but only when the non template function and template function are equally good. In that case the non template function is used.
In this case though they are not both equally good. t2
is a TheTest
, when overload resolution runs it finds void handle(ITest &t)
and void handle(TheTest par)
(I've instantiated the template here). Sine the template version will give an exact match it is a better function and is chosen.
The way to fix this is to constrain the template to only work for types that aren't derived from ITest
. If you change the template function to
template<typename T, std::enable_if_t<!std::is_base_of_v<ITest, T>, bool> = true>
void handle(T par)
{
par++;
}
Then it will only be called for types that don't derive from ITest
. You can see it working in this live example.