Cv-qualifications of prvalues (revisited)

C++Language LawyerC++17Temporary ObjectsPrvalue

C++ Problem Overview


This is a followup to my previous question, where the apparent consensus was that the change in treatment of cv-qualifications of prvalues was just a fairly minor and inconsequential change intended to solve some inconsistencies (e.g. functions returning prvalues and declared with cv-qualified return types).

However, I see another place in the standard that appears to rely on prvalues having cv-qualified types: initialization of const references with prvalues through temporary materialization conversion. The relevant wording can be found in multiple spots in 9.3.3/5

> [...] If the converted initializer is a prvalue, its type T4 is adjusted to type “cv1 T4” ([conv.qual]) and the temporary materialization conversion ([conv.rval]) is applied [...] > > [...] Otherwise, the initializer expression is implicitly converted to a prvalue of type “cv1 T1”. The temporary materialization conversion is applied and the reference is bound to the result.

The intent is obviously to make sure that when we get to the actual temporary materialization conversion

> 7.3.4 Temporary materialization conversion
> 1 A prvalue of type T can be converted to an xvalue of type T. This conversion initializes a temporary object ([class.temporary]) of type T from the prvalue by evaluating the prvalue with the temporary object as its result object, and produces an xvalue denoting the temporary object. [...]

the type T that it receives as input includes the required cv-qualifications.

But how does that cv-qualification survive the 7.2.2/2 in case of non-class non-array prvalue?

> 7.2.2 Type
> 2 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.

Or does it?

E.g. what kind of temporary do we get in this example

const int &r = 42;

Is the temporary const or not? Can we do

const_cast<int &>(r) = 101; // Undefined or not?

without triggering undefined behavior? If I'm not mistaken, the original intent was to obtain a const int temporary in such cases. Is it still true? (For class types the answer is clear - we get a const temporary.)

C++ Solutions


Solution 1 - C++

Why are you doubting the language of 7.2.2? This seems pretty unambiguous that cv qualifiers are discarded on non-class, non-array prvalues, so the type T in temporary materialization is a non-const, non-volatile type.

If that weren't the case, then you wouldn't be able to bind prvalues to non-const rvalue references. Yet it seems overwhelmingly likely that the standard was intended to accept programs such as this:

#include <type_traits>

template<typename T> void
f(T &&t)
{
  static_assert(std::is_same_v<decltype(t), int&&>);
  ++t;
}

int
main()
{
  f(5);
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAnTView Question on Stackoverflow
Solution 1 - C++user3188445View Answer on Stackoverflow