Title 2160. Issues with partial ordering
Status open Section [temp.func.order]
Submitter Richard Smith

Created on 2015-07-16.00:00:00 by admin, last changed by admin.

msg5805 (view) Date: 2016-02-15.00:00:00

Notes from the February, 2016 meeting:

None of these examples appears to reflect a defect in the current wording; in particular, the second and third examples involve a dependent type and there could be a later specialization of identity, so it's impossible to reason about those cases in the template definition context. The issue will be left open to allow for possible clarification of the intent of the wording.

msg5666 (view) Date: 2017-02-06.00:00:00

(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) [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).

Non-deduced 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 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.

Date User Action Args
2017-02-06 00:00:00adminsetmessages: + msg5805
2015-07-16 00:00:00admincreate