Title
Incorrect definition of implicit conversion sequence
Status
drafting
Section
12.2.4.2.1 [over.best.ics.general]
Submitter
Jim X

Created on 2021-09-25.00:00:00 last changed 14 months ago

Messages

Date: 2023-02-06.20:43:48

CWG 2023-02-06

Additional drafting is needed to cover e.g. conversions from literal 0 to null pointer constants.

Date: 2022-12-03.20:29:13

Proposed resolution (approved by CWG 2022-12-02):

Change 12.2.4.2.1 [over.best.ics.general] paragraph 1, merging it with paragraph 2,as follows:

An implicit conversion sequence is a sequence of conversions used to convert an argument in a function call to the type of the corresponding parameter of the function being called. The sequence of conversions is an implicit conversion as defined in 7.3 [conv], which means; it is governed by thus based on the rules for initialization of an object or reference by a single expression (9.4 [dcl.init], 9.4.4 [dcl.init.ref]). Implicit, except that implicit conversion sequences are concerned only with the type, cv-qualification, and value category of the argument and how these are converted to match the corresponding properties of the parameter. [Note: ... ]
Date: 2021-09-25.00:00:00

According to 12.2.4.2.1 [over.best.ics.general] paragraphs 1 and 9,

An implicit conversion sequence is a sequence of conversions used to convert an argument in a function call to the type of the corresponding parameter of the function being called. The sequence of conversions is an implicit conversion as defined in 7.3 [conv], which means it is governed by the rules for initialization of an object or reference by a single expression (9.4 [dcl.init], 9.4.4 [dcl.init.ref]).

If no sequence of conversions can be found to convert an argument to a parameter type, an implicit conversion sequence cannot be formed.

However, 7.3.1 [conv.general] paragraph 3 says,

An expression E can be implicitly converted to a type T if and only if the declaration T t=E; is well-formed, for some invented temporary variable t (9.4 [dcl.init]).

This definition is too restrictive in the context of overload resolution's implicit conversion sequences. The intent, as stated in 12.2.1 [over.match.general] note 1, is that overload resolution ignores some factors that would make such an initialization ill-formed, and these are applied only after the best match is determined:

[Note 1: The function selected by overload resolution is not guaranteed to be appropriate for the context. Other restrictions, such as the accessibility of the function, can make its use in the calling context ill-formed. —end note]

For example,

  struct A{
    A(int) = delete;
  };
  struct B{
     B(int) {}
  };
  void fun(A); // #1
  void fun(B); // #2
  int main() {
    fun(0);    // #3
  }

The intent is that overload #1 be viable with a valid implicit conversion sequence, making the call at #3 ambiguous, even though the hypothetical declaration

  A t = 1;

would be ill-formed.

History
Date User Action Args
2023-02-06 20:43:48adminsetmessages: + msg7159
2023-02-06 20:43:48adminsetstatus: tentatively ready -> drafting
2022-12-03 20:29:13adminsetmessages: + msg7077
2022-12-03 20:29:13adminsetstatus: drafting -> tentatively ready
2022-11-20 07:54:16adminsetstatus: open -> drafting
2021-09-25 00:00:00admincreate