A *cv-decomposition* of a type T
is a sequence of
and
such that T is
“ ⋯ U” for ,
where
each is a set of cv-qualifiers ([basic.type.qualifier]), and
each is
“pointer to” ([dcl.ptr]),
“pointer to member of class of type” ([dcl.mptr]),
“array of ”, or
“array of unknown bound of” ([dcl.array]).

If designates an array,
the cv-qualifiers on the element type are also taken as
the cv-qualifiers of the array.

[ Example ]

The n-tuple of cv-qualifiers after the first one
in the longest cv-decomposition of T, that is,
, is called the
*cv-qualification signature* of T.

The *cv-combined type* of two types T1 and T2
is the type T3
similar to T1 whose cv-decomposition is such that:

- for every , is the union of and ;
- if either or is “array of unknown bound of”, is “array of unknown bound of”, otherwise it is ;
- if the resulting is different from or , or the resulting is different from or , then const is added to every for .

[ Note

: *end note*

]If a program could assign a pointer of type T** to a pointer of
type const T** (that is, if line #1 below were
allowed), a program could inadvertently modify a const object
(as it is done on line #2).

For example,

— int main() { const char c = 'c'; char* pc; const char** pcc = &pc; // #1: not allowed *pcc = &c; *pc = 'C'; // #2: modifies a const object }

[ Note

: *end note*

]A prvalue of type “pointer to cv1 T” can be
converted to a prvalue of type “pointer to cv2 T” if
“cv2 T” is more cv-qualified than “cv1
T”.

A prvalue of type “pointer to member of X of type cv1
T” can be converted to a prvalue of type “pointer to member
of X of type cv2 T” if “cv2
T” is more cv-qualified than “cv1 T”.

—