You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
There are several details in the template partial ordering rules that are underspecified. Both gcc and clang seem to agree on the algorithm for determining template ordering, but that algorithm doesn't actually appear in the standard. In no particular order:
temp.deduct.type/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).
Non-Deduced Context Omission
Same as previous example, but 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 non-deduced 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 non-deduced context argument, as long as that parameter type is deduced from a different template parameter type that did get matched.
The approaches that gcc/clang take make sense - but those rules should be spelled out in the standard.
The text was updated successfully, but these errors were encountered:
For the first issue, isn't it the case that [temp.deduct.partial]/8 tells us to use the [temp.deduct.type] rules to perform the deduction for one function template against the other transformed function type, so [temp.deduct.type]/2 would also apply in the partial ordering context?
There are several details in the template partial ordering rules that are underspecified. Both gcc and clang seem to agree on the algorithm for determining template ordering, but that algorithm doesn't actually appear in the standard. In no particular order:
Consistency of deduced values:
temp.deduct.type/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
Here, if synthesized for (2)
Unique2
andtypename identity<Unique2>::type == Unique2
, then type deduction would succeed in both directions and the callbar(0,0)
would be ambiguous. However, it seems that both compilers instead simply treattypename identity<Unique2>::type
asUnique2_b
, thus making template deduction from (2) to (1) fail (based on the implied missing Consistency rule).Non-Deduced Context Omission
Same as previous example, but now define:
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
againstUnique1
and then have the non-deduced contexttypename identity<Unique1>::type
to match againstUnique1
, 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 non-deduced context argument, as long as that parameter type is deduced from a different template parameter type that did get matched.The approaches that gcc/clang take make sense - but those rules should be spelled out in the standard.
The text was updated successfully, but these errors were encountered: