Search code examples
c++constantslanguage-lawyervolatile

Clarification about conv.qual#1


conv.qual#1:

A qualification-decomposition of a type T is a sequence of cvi and Pi such that T is

“cv0 P0 cv1 P1 ⋯ cv_n-1 Pn-1 cvn U” for n ≥ 0,

where each cvi is a set of cv-qualifiers ([basic.type.qualifier]), and each Pi is “pointer to” ([dcl.ptr]), […]

[Example 1: The type denoted by the type-id const int ** has three qualification-decompositions, taking U as “int”, as “pointer to const int”, and as “pointer to pointer to const int”. — end example]

I don't understand how the description "“cv0 P0 cv1 P1 ⋯ cv_n-1 Pn-1 cvn U” for n ≥ 0," is compatible with the example.

I mean, the example is for T == const int** and a possible decomposition is said to exist for U being int. How is that even possible? How can const int** (T) be written as cv0 P0 cv1 P1 ⋯ cv_n-1 Pn-1 cvn int?

But more in general, I don't understrand why U is at the end instead of the beginning of that cv0 P0 cv1 P1 ⋯ cv_n-1 Pn-1 cvn U_. How can anything starting with, say, const * volatile * const* be a type?


Solution

  • cv_0 P_0 cv_1 P_1 ⋯ cv_n-1 P_n-1 cv_n U is not meant to represent the syntactic form of a type-id such as const int**.

    It is meant to represent the formal full-text name for a type after replacing U, Ps and cvs.

    As the note says the type formed by the type-id const int** is formally "pointer to pointer to const int" (and int const** would form this same type).

    You get this formal name from cv_0 P_0 cv_1 P_1 ⋯ cv_n-1 P_n-1 cv_n U by choosing n = 2 and replacing U by int, cv_2 by const, P_1 by "pointer to", P_0 by "pointer to" and the remaining cv by .