Is it legal to cast a non-classical non-array value to the cv class?
I was reading the value categories and came across the following (many omitted for brevity):
The following expressions are prvalue expressions:
- a literal (other than a string literal), such as 42, true, or nullptr;
Properties:
- A non-classical non-massive value cannot be cv-qualified.
But ... the following program compiles and works fine on ideone.com and with g ++ 5.4.0:
#include <iostream>
int main() {
std::cout << ((const int) 42) << std::endl;
}
I understand that compilers provide extensions and can do their best if undefined behavior hits. I'm just trying to figure out what the standard mandates mean.
In N4296 I found the following for the relevant passage:
[expression]
[... content omitted ...]
- If the original prvalue is of type "cv T", where T is cv-unqualified non-class, non-array type, the expression type is promoted to T. before any further analysis.
The term "initially" is what leaves me. It is unclear if this is allowed as a result of another expression, for example, the user can explicitly specify a non-array for a class with cv qualifications (which gives a different prvalue), or it only applies to the "root" "expression ( 42
in this case).
My question is, does the standard allow such expressions (which just drop the cv qualifiers), or is it forbidden (and where applicable)?
source to share
Thanks to SanderDeDycker for pointing out the relevant part of the standard for search.
My question will be answered in the following section N4296 (emphasis mine):
[expr.cast]
- The result of the expression (T) of the expression-expression is of type T. the result is an lvalue if T is an lvalue reference type, or an rvalue reference to a function type and an x value if T is an rvalue reference to an object type; otherwise, the result is prvalue. [Note: if T is a non-class type that is a cv-qualifier, the cv-qualifiers are discarded when defining the return type; see section 5. - end note]
So we can conclude that type expressions (const int) 42
are perfectly legal C ++.
source to share
You should be aware that cppreference is not normative. "Can not" can be read in two ways:
-
Forbidden, ala "must not"
-
It just can't be, ala invariants
Quote quoted in the text:
If the original prvalue is of type "cv T", where T is cv-unqualified non-class, non-array type, the expression type is promoted to T. before any further analysis.
suggests me that a qualified prvalue rejects qualification in the same way that arrays can decay into pointers (to clarify, this rule doesn't happen at the point where a cast would be poorly formed). Defect # 1261 makes the language pretty explicit about what happens where.
source to share