It seems that a template-function has always precedence over a non-template function if the function argument doesn't match the type of the non-template function's argument exactly, but is a derived type, i.e., with the declarations
1 2 3 4 5
struct A { ... };
struct B: A { ... };
B object;
template <typename T> void func(const T &x);
void func(const A &x);
calling func(object) uses the template variant of func(), only func((A&)object) uses the non-template variant.
So my question is: is there any way to modify the declarations such that func(object) uses the non-template variant, even if "object" is an instance of a derived type of A?
Thanks & kind regards,
Markus
P.S.: here is a full example demonstrating the above-mentioned behaviour:
That is odd. According to "C++ Templates: The Complete Guide" (Vandervoorde & Josuttis):
...a nontemplate function can coexist with a function template that has the same name and parameters and can be instantiated with the same type. All other factors being equal, the overload resolution process normally prefers this nontemplate over one generated from the template.
edit: Just tested it myself.
$ ./a
void func(const A &x)
void A::func() const
template <typename T> void func(const T &x)
void B::func() const
void func(const A &x)
void B::func() const
template <typename T> void func(const T &x)
void C::func() const
This appears to be the correct output with the nontemplate taking precedence? Perhaps it is compiler specific? I was using gnu.
The statement "func(b);" in line 39 of the code example calls the template function, which corresponds to the 3rd line in your program output. Only if the object is explicitly cast to the base class ("func((A &)b);" in line 40), the non-template function is called (5th line in your output).
BTW, I tried the example with MSVC2005 and gcc-4.5 (MinGW) and got results identical to your posted output. I would like to see
void func(const A &x)
void A::func() const
void func(const A &x)
void B::func() const
void func(const A &x)
void B::func() const
template <typename T> void func(const T &x)
void C::func() const
instead (note the difference in the 3rd line). Can this be done without an explicit cast (as in "func((A &)b);")?
This certainly works (I rewrote the example using pointers, see below), but the objects I want to pass into the function are not created as pointers, and rewriting the entire code using new/delete is not an option. So my question is still open, do you have further ideas (or at least a clarification that it is not possible at all)?
All other factors being equal, the overload resolution process normally prefers this nontemplate over one generated from the template.
They are not the same, because implies an implicit conversion.
Instead of executing the implicit conversion, the code is generated trough the template (maybe is implementation dependent)
Thanks for the proposal, this is what I am currently doing. However, it is somewhat inconvenient and error prone, so I would prefer if it could be done automatically, i.e., if I could somehow tell the compiler to prefer the function which takes the base class pointer (or reference) argument over the template function. Is there any way of doing this?