(From this
editorial issue.)
Consistency of deduced values
template <typename T> void foo(T, T); // (1)
template <typename T, typename U> void foo(T, U); // (2)
14.8.2.5 [temp.deduct.type] paragraph 2 makes it clear
that there must be exactly one set of deduced values for the
Ps. But there is no such statement in the partial ordering
rule. The algorithm described only does pairwise P/A
matching, so a synthesized call from (2) to (1) via foo(U{},
V{}) could succeed in deduction. Both gcc and clang agree
that (1) is more specialized.
Type Synthesis Template Instantiation
template <typename T>
struct identity { using type = T; };
template<typename T> void bar(T, T ); // (1)
template<typename T> void bar(T, typename identity<T>::type ); // (2)
Here, if synthesized for (2) Unique2 and typename
identity<Unique2>::type == Unique2 , then type
deduction would succeed in both directions and the call
bar(0,0) would be ambiguous. However, it seems that
both compilers instead simply treat typename
identity<Unique2>::type as Unique2_b,
thus making template deduction from (2) to (1) fail (based
on the implied missing Consistency rule).
Nondeduced Context Omission
This is the same as the previous example, except now define
template <typename T> struct identity;
template <> struct identity<int> { using type = int; };
With no template instantiation during synthesis and
consistency, the (2) ==> (1) deduction fails. But if we
consider the (1) ==> (2) call, we'd match T against
Unique1 and then have the nondeduced
context typename identity<Unique1>::type to
match against Unique1, but that would be a
substitution failure. It seems that the approach taken by
gcc and clang (both of which prefer (1) here) is to ignore
the nondeduced context argument, as long as that parameter
type is deduced from a different template parameter type
that did get matched.
