A qualification-decomposition of a type
T
is a sequence of cvi and Pi such thatT
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 constint
”, and as “pointer to pointer toconst 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?
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
, P
s and cv
s.
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
.