On gcc 4.9.0
:
#include <iostream>
#include <map>
struct A
{
typedef int type;
};
template<typename T> void foo(T*) { std::cout << "a" << std::endl; }
template<typename T> void foo(typename T::type*) { std::cout << "b" << std::endl; }
template<typename T>
struct identity
{
typedef T type;
};
template<typename T> void bar(T*) { std::cout << "a" << std::endl; }
template<typename T> void bar(typename identity<T>::type*) { std::cout << "b" << std::endl; }
int main()
{
//auto f = foo<A>; // ambiguous
foo<A>(0); // prints "b", as the second overload is more specific
auto b = bar<A>; // fine
bar<A>(0); // prints "b", as the second overload is more specific (?)
b(0); // prints "b"
return 0;
}
Any clue on why the address can be taken, in the second case?
The deduction for auto
is the same as template deduction. From [dcl.spec.auto]:
When a variable declared using a placeholder type is initialized, [...], the deduced return type or variable type is determined from the type of its initializer. If the placeholder is the auto type-specifier, the deduced type is determined using the rules for template argument deduction. If the placeholder is the
auto
type-specifier, the deduced type is determined using the rules for template argument deduction.
So when we have either:
auto f = foo<A>;
auto b = bar<A>;
We are performing type deduction as if we called (to borrow T.C.'s choice of words):
template <typename M> void meow(M );
meow(foo<A> );
meow(bar<A> );
and using the deduced type M
as the type of f
and b
, respectively.
But, according to [temp.deduct.type], emphasis mine:
If a template parameter is used only in non-deduced contexts and is not explicitly specified, template argument deduction fails.
The non-deduced contexts are:
— [...]
— A function parameter for which argument deduction cannot be done because the associated function argument is a function, or a set of overloaded functions (13.4), and one or more of the following apply:
— more than one function matches the function parameter type (resulting in an ambiguous deduction), or
— no function matches the function parameter type, or
— the set of functions supplied as an argument contains one or more function templates.
— [...]
In both cases, the argument is a set of overloaded functions which contains one or more function templates - which makes it a non-deduced context, so template argument deduction fails. Thus, clang is correct in rejecting both initializations.
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