A *qualification-decomposition* of a type T
is a sequence of
and
such that T is
“ ⋯ U” for n ≥ 0,
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.

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

The *qualification-combined type* of two types T1 and T2
is the type T3
similar to T1 whose qualification-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 , and
- if the resulting is different from or , or the resulting is different from or , then const is added to every for ,

A prvalue of type T1
can be converted to type T2
if the qualification-combined type of T1 and T2 is T2.

[*Note 1*: *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 3*: *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”.

—