What Does "Cv-Unqualified" Mean in C++

What does cv-unqualified mean in C++?

There are fundamental types and compound types. Fundamental types are the arithmetic types, void, and std::nullptr_t. Compound types are arrays, functions, pointers, references, classes, unions, enumerations, and pointers to non-static members.

A cv-unqualified type is any of those types.

For any cv-unqualified type, there are three corresponding cv-qualified types:

  • const-qualified - with the const cv-qualifier
  • volatile-qualified - with the volatile cv-qualifier
  • const-volatile-qualified - with both the const and volatile cv-qualifiers

Note, however, that cv-qualifiers applied to an array type actually apply to its elements.

The cv-qualified and cv-unqualified types are distinct. That is int is a distinct type from const int.

What Does cv-qualified Mean?

c in cv means const and v means volatile.

From the C++ Standard (3.9.3 CV-qualifiers)

  • The term object type (1.8) includes the cv-qualifiers specified in the decl-specifier-seq (7.1), declarator (Clause 8), type-id (8.1), or newtype - id (5.3.4) when the object is created.

  • A const object is an object of type const T or a non-mutable subobject of such an object.

  • A volatile object is an object of type volatile T, a subobject of such an object, or a mutable subobject of a const volatile object.

  • A const volatile object is an object of type const volatile T, a non-mutable subobject of such an object, a const subobject of a volatile object, or a non-mutable volatile subobject of a const object.

Cv-qualifications of prvalues in C++14

According to the commit on github, this was done to resolve CWG1261: Explicit handling of cv-qualification with non-class prvalues

Based on comments to the question it seems there was room for surprising variations in type category of this (formally a prvalue) and that gcc formerly and MSVC currently instead used a const lvalue.

The wording tightens up the hole to be explicit that, e.g., even if this is by some compiler-internal magic a prvalue of type X* const, prior to any further analysis it is adjusted to X*.

Similarly, your given example does look like a gcc bug. Possibly decltype isn't looking at the value type before applying the c-style cast.

The reason it's now a note in [basic.lval]/4 is that it's now a consequence of the new text in [expr]/6, rather than specifying the rule in [basic.lval]/4.

Full credit to T.C. for having basically answered this in the comments on the question, including the reference to the gcc bug-fix, and various other examples of previously under-specified behaviours for cv-qualified non-class non-array prvalues.

cv qualifiers in decltype of prvalue expression

As per the CPP standard draft n4713:

8.2.1 Value category [basic.lval]
...

9. ... Class prvalues can have cv-qualified types; non-class prvalues always have cv-unqualified types.

Since (i + j) evaluates to a non-class prvalue, it will have a cv-unqualified type and using decltype on it yields an int.

What is the relevance of this statement in 7.1.6.1/1 in the C++ Standard?

Sure, most class and enum definitions make use of it:

struct A { }; // valid
const struct B { }; // invalid, const would have no meaning
const struct C { } c { }; // valid

There is nothing else. An init-declarator-list is only used in a simple-declaration, and for that, the standard (C++11) states:

7 Declarations [dcl.dcl]

3 In a simple-declaration, the optional init-declarator-list can be omitted only when declaring a class (Clause 9) or enumeration (7.2), that is, when the decl-specifier-seq contains either a class-specifier, an elaborated-type-specifier with a class-key (9.1), or an enum-specifier.

Correlation between specifier and qualifier?

Most of it doesn't make sense.

Specifier and qualifier are defined in the C++ standard. Qualifier is just an integral part of a specifier. For example, type specifier in a declaration can include cv-qualifiers. I don't see the reason to quote everything from the standard on this topic.

Cv-qualifiers are not restricted to lvalues. Rvalues of class types can also be cv-qualified. It is possible to cv-qualify an rvalue of non-class type, but it will have no effect and will be ignored.

The use of const qualifier that you show in your example with foo is just a syntactic form, which actually means that the const-qualifier is applied to the implied this parameter of the foo method: const A* this. I.e. in this case it does indeed qualify an lvalue, but it is *this, not foo.

The term qualifier also appears in the context of qualified names. Name like some_class::some_member (or some_namespace::some_name) are called qualified names and the some_class:: part is a qualifier.

The idea that if something is an lvalue then you can modify it is totally incorrect. There are modifiable lvalues and non-modifiable lvalues. An object declared as const int i = 5 is an lvalue, yet you can't modify it. Ordinary functions are also lvalues in C++, yet you can't modify a function.



Related Topics



Leave a reply



Submit