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

2024-12-19


2481. Cv-qualification of temporary to which a reference is bound

Section: 9.4.4  [dcl.init.ref]     Status: CD6     Submitter: Jiang An     Date: 2021-03-20

[Accepted as a DR at the June, 2021 meeting.]

According to 9.4.4 [dcl.init.ref] bullet 5.4.2, when a reference is initialized with a non-class value and the referenced type is not reference-related to the type of the initializer,

According to 7.2.2 [expr.type] paragraph 2, the cv-qualification is discarded before invoking the temporary materialization conversion:

If a prvalue initially has the type “cv T”, where T is a cv-unqualified non-class, non-array type, the type of the expression is adjusted to T prior to any further analysis.

This results in a reference-to-const being bound to a non-const object, meaning that a const_cast of the reference to a reference-to-nonconst would allow a well-defined modification of the value:

  constexpr const int &r = 42;
  const_cast<int &>(r) = 23;  // Well-defined
  static_assert(r == 42);     // Ill-formed, non-constant expression

This was different from the situation before the advent of the temporary materialization conversion in C++17, when the description of the reference binding created the temporary explicitly with the cv-qualified type:

If T1 is a non-class type, a temporary of type “cv1 T1” is created and copy-initialized (8.5) from the initializer expression. The reference is then bound to the temporary.

Presumably this difference was unintentional and should be reverted.

Proposed resolution, May, 2021:

Change 9.4.4 [dcl.init.ref] bullet 5.4.2 as follows:

A reference to type “cv1 T1” is initialized by an expression of type “cv2 T2” as follows: