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.