Title
Distinguishing user-defined conversion sequences by ref-qualifier
Status
nad
Section
12.2.4.3 [over.ics.rank]
Submitter
Hani Deek

Created on 2021-09-09.00:00:00 last changed 17 months ago

Messages

Date: 2022-11-20.07:54:16

CWG 2022-11-11

This is an extension that is best addressed by a paper to EWG.

Date: 2022-02-18.07:47:23

Suggested resolution:

Change 12.2.4.3 [over.ics.rank] bullet 3.3 as follows:

  • User-defined conversion sequence U1 is a better conversion sequence than another user-defined conversion sequence U2 if

    • the initial standard conversion sequence of U1 is better than the initial standard conversion sequence of U2, or

    • they contain the same user-defined conversion function or constructor or they initialize the same class in an aggregate initialization and in either case the second standard conversion sequence of U1 is better than the second standard conversion sequence of U2.

Date: 2022-02-18.07:47:23

Consider the following example:

  struct S  {
      operator int() const & { return 0; }
      operator char() && { return 0; }
  };

  void foo(int) {}
  void foo(char) {}

  int main() {
    foo(S{}); //OK, calls foo(char)
  }

Here, the ICS for each function is a user-defined conversion involving the same user-defined conversion function, operator char() &&, because of 12.2.4.3 [over.ics.rank] bullet 3.2.3:

S1 and S2 include reference bindings (9.4.4 [dcl.init.ref]) and neither refers to an implicit object parameter of a non-static member function declared without a ref-qualifier, and S1 binds an rvalue reference to an rvalue and S2 binds an lvalue reference

foo(int) is a promotion, while foo(char) is an exact match, so the latter is chosen.

Replacing int and char in this example with non-interconvertible types results in a different outcome:

  class A{};
  class B{};

  struct S {
    operator A() const & { return A{}; }
    operator B() && { return B{}; }
  };

  void foo(A) {}
  void foo(B) {}

  int main() {
    foo(S{}); //error: call to foo is ambiguous
  }

Here, only one of the two user-defined conversion operators is viable for each overload. Consequently, 12.2.4.3 [over.ics.rank] bullet 3.3,

User-defined conversion sequence U1 is a better conversion sequence than another user-defined conversion sequence U2 if they contain the same user-defined conversion function or constructor or they initialize the same class in an aggregate initialization and in either case the second standard conversion sequence of U1 is better than the second standard conversion sequence of U2.

does not apply, unlike the earlier case, because different user-defined conversion functions appear in each conversion sequence and thus the sequences are indistinghishable.

This seems inconsistent.

History
Date User Action Args
2022-11-20 07:54:16adminsetmessages: + msg7049
2022-11-20 07:54:16adminsetstatus: open -> nad
2022-02-18 07:47:23adminsetmessages: + msg6727
2021-09-09 00:00:00admincreate