Why, in the below, is the call to an instantiation of bar
not ambiguous, while the non-template overloaded function foo
is ambiguous. It is the same for nullptr
instead of NULL
#include <iostream>
template<typename T>
void bar (T*)
{
std::cout << "bar(T*)" << std::endl;
}
template<typename T>
void bar (typename T::value_type *)
{
std::cout << "bar(T::value_type*)" << std::endl;
}
struct A
{
using value_type = int;
};
void foo (A::value_type*)
{
std::cout << "foo(A::value_type *)" << std::endl;
}
void foo (A*)
{
std::cout << "foo(A *)" << std::endl;
}
int main ()
{
bar<A> (NULL);
foo (NULL); // ambigous
}
EDIT: To be clear. I expect the foo
overload to be ambiguous. I don't understand why the bar
overloads generated when I instantiate bar<A>
are not equally ambiguous.
Template Function Overloading:The name of the function templates are the same but called with different arguments is known as function template overloading. If the function template is with the ordinary template, the name of the function remains the same but the number of parameters differs.
In Function overloading, sometimes a situation can occur when the compiler is unable to choose between two correctly overloaded functions. This situation is said to be ambiguous. Ambiguous statements are error-generating statements and the programs containing ambiguity will not compile.
Function overloading is used when multiple functions do similar operations; templates are used when multiple functions do identical operations. Templates provide an advantage when you want to perform the same action on types that can be different.
You may overload a function template either by a non-template function or by another function template. The function call f(1, 2) could match the argument types of both the template function and the non-template function.
The rules for determining which overload is the best viable candidate as the last tiebreaker include, from [over.match.best]:
Given these definitions, a viable function F1 is defined to be a better function than another viable function F2 if for all arguments i, ICSi(F1) is not a worse conversion sequence than ICSi(F2), and then
— [...]
— F1 and F2 are function template specializations, and the function template for F1 is more specialized than the template for F2 according to the partial ordering rules described in 14.5.6.2.
That bullet point is reached only if we have two functions with identical conversion sequences in which either both are or both aren't function templates. For foo
, both our overload candidates have identical conversion sequences, neither are function templates, and this last bullet point doesn't apply - so it's ambiguous.
For bar
though, we can try to see if one or the other of
template<typename T> void bar (T*) // (1)
template<typename T> void bar (typename T::value_type *) // (2)
is more partially specialized than the other. The rules for that are basically to try to see if you can call one function with the other's argument. In this case, any typename T::value_type*
is still a pointer, so you could call the T*
overload with it. However, in the other direction, template deduction would fail as typename T::value_type
is a non-deduced context. So (2)
is considered more partially specialized and so it's chosen as the best viable candidate. No ambiguity.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With