This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115d. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2024-10-26


2445. Partial ordering with rewritten candidates

Section: 13.7.7.3  [temp.func.order]     Status: C++20     Submitter: Hubert Tong     Date: 2020-01-29

[Accepted at the February, 2020 (Prague) meeting.]

The tiebreaker based on partial ordering of function templates should presumably operate upon rewritten candidates based on their parameter lists for the purpose of overload resolution (12.2.2 [over.match.funcs]) without substitution of template arguments instead of the function parameter lists of the templates themselves.

It is observed, however, that neither GCC nor Clang performs partial ordering in the manner described above. In the following case, considering the templates with the reordering should yield 1a as being more specialized than 2; however, the wording is not especially clear about this and both GCC and Clang seems to fall past the partial ordering tiebreaker to pick 2 for the case as-is. If 1b is introduced, then it is more specialized than 2 in either ordering, and it is chosen by both GCC and Clang.

  template <typename> constexpr bool F = false;
  template <typename T> struct A { };

  template <typename T, typename U>
  // bool operator==(A<T>, A<U *>);       // 1b
  bool operator==(T, A<U *>);             // 1a

  template <typename T, typename U>
  bool operator!=(A<T>, U) {              // 2
   static_assert(F<T>, "Isn't this less specialized?");
   return false;
  }

  bool f(A<int> ax, A<int *> ay) { return ay != ax; }

Proposed resolution (February, 2020):

Change 13.7.7.3 [temp.func.order] paragraph 3 as follows:

To produce the transformed template, for each type, non-type, or template template parameter (including template parameter packs (13.7.4 [temp.variadic]) thereof) synthesize a unique type, value, or class template respectively and substitute it for each occurrence of that parameter in the function type of the template. [Note: The type replacing the placeholder in the type of the value synthesized for a non-type template parameter is also a unique synthesized type. —end note] If only one of the Each function templates template M that is a member function, and that function is a non-static member of some class A, M is considered to have a new first parameter of type X(M), described below, inserted in its function parameter list. Given cv as the If exactly one of the function templates was considered by overload resolution via a rewritten candidate (12.2.2.3 [over.match.oper]) with a reversed order of parameters, then the order of the function parameters in its transformed template is reversed. For a function template M with cv-qualifiers of M (if any), the new parameter cv that is a member of a class A:

[Note: This allows...