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
[Accepted as a DR at the March, 2024 meeting.]
Consider:
int foo(int*& r); // #1 int foo(const int* const& r); // #2 int *p; int x = foo(p);
Both #1 and #2 perform direct reference binding; no qualification conversions are involved. Despite the lack of a rule, implementations prefer #1 over #2.
Proposed resolution (approved by CWG 2023-11-10):
Change in 12.2.4.2.5 [over.ics.ref] paragraph 1 as follows:
When a parameter ofreferencetype "reference to cv T" binds directly (9.4.4 [dcl.init.ref]) to an argument expression, the implicit conversion sequence is the identity conversion, unless:
- If the argument expression has a type that is a derived class of the parameter type,
in which casethe implicit conversion sequence is a derived-to-base conversion (12.2.4.2 [over.best.ics]).- Otherwise, if T is a function type, or if the type of the argument is possibly cv-qualified T, or if T is an array type of unknown bound with element type U and the argument has an array type of known bound whose element type is possibly cv-qualified U, the implicit conversion sequence is the identity conversion. [ Note: When T is a function type, the type of the argument may differ only by the presence of noexcept. -- end note]
- Otherwise, the implicit conversion sequence is a qualification conversion.
[Example 1: ... —end example]
If the parameter binds directly to the result of applying a conversion function to the argument expression, the implicit conversion sequence is a user-defined conversion sequence (12.2.4.2.3 [over.ics.user]) whose second standard conversion sequence iseither an identity conversion or, if the conversion function returns an entity of a type that is a derived class of the parameter type, a derived-to-base conversiondetermined by the above rules.
Change in 12.2.4.3 [over.ics.rank] bullet 3.2.5 as follows:
- S1 and S2 differ only in their qualification conversion (7.3.6 [conv.qual]) and yield similar types T1 and T2, respectively (where a standard conversion sequence that is a reference binding is considered to yield the cv-unqualified referenced type), where T1
can be converted to T2 by a qualification conversionand T2 are not the same type, and const T2 is reference-compatible with T1 (9.4.4 [dcl.init.ref]). [Example 5:int f(const volatile int *); int f(const int *); int i; int j = f(&i); // calls f(const int*) int g(const int*); int g(const volatile int* const&); int* p; int k = g(p); // calls g(const int*)-- end example] or, if not that,
Change in 12.2.4.3 [over.ics.rank] bullet 3.2.6 as follows:
- S1 and S2
include reference bindingsbind "reference to T1" and "reference to T2", respectively (9.4.4 [dcl.init.ref]),and the types to which the references refer are the same type except for top-level cv-qualifiers, and the type to which the reference initialized by S2 refers is more cv-qualified than the type to which the reference initialized by S1 referswhere T1 and T2 are not the same type, and T2 is reference-compatible with T1. [Example 6: ...int h1(int (&)[]); int h1(int (&)[1]); int h2(void (&)()); int h2(void (&)() noexcept); void g2() { int a[1]; h1(a); // calls h1(int (&)[1]) extern void f2() noexcept; h2(f2); // calls h2(void (&)() noexcept) }-- end example ]