In different places in the C++ (C++11) standard, declarations are described in terms of derived-declarator-type-list. I am studying rvalue references and the use of this term is critical in that context (§8.3.2):
In a declaration T D where D has either of the forms
& attribute-specifier-seqopt D1
&& attribute-specifier-seqopt D1
and the type of the identifier in the declaration T D1 is
“derived-declarator-type-list T,” then the type of the identifier of D
is “derived-declarator-type-list reference to T.”
Unfortunately, the category "derived-declarator-type" is never defined in the standard. (I looked through every use of the word "derived", and in addition this is possibly confirmed here and here.)
Because "derived-declarator-type-list" is italicized, I assume it refers to a category, and not to a variable label such as T
(and therefore, I disagree with Doug Gwyn's assessment in the second link I just gave that "we could have used X
instead of 'derived-declarator-type-list' ").
What is the definition of derived-declarator-type in the C++11 standard?
It's being defined right there and then. It's a way of carrying whatever comes before T
across to the next type, similar to:
<some stuff> T
<some stuff> reference to T
It's just whatever comes before T
in the type of T D1
.
For example, if you have the declaration int& (*const * p)[30]
, T
is int
, D
is & (*const * p)[30]
and D1
is (*const * p)[30]
. The type of T D1
is "pointer to const pointer to array of 30 int". And so, according to the rule you quoted, the type of p
is "pointer to const pointer to array of 30 reference to int".
Of course, this declaration is then disallowed by §3.4.2/5:
There shall be no references to references, no arrays of references, and no pointers to references.
I think the informal terminology of it being a derived declarator type list comes from the C standard's definition of a derived type (similar to a compound type in C++):
Any number of derived types can be constructed from the object, function, and
incomplete types, as follows:
- An array type [...]
- An structure type [...]
- An union type [...]
- An function type [...]
- An pointer type [...]
In response to the comments: It seems you're getting confused between the type and the declarator. For example, if int* p
is the declarator, then the type of p
is "pointer to int". The type is expressed as these English-like sentences.
Example 1: int *(&p)[30]
This is a declaration T D
where (§8.3.1 Pointers):
D
has the form:
*
attribute-specifier-seqopt cv-qualifier-seqopt D1
where D1
is (&p)[3]
. That means T D1
is of the form int (&p)[3]
which has type "reference to array of 3 int
" (you work this out recursively, next step using §8.3.4 Arrays and so on). Everything before the int
is the derived-declarator-type-list. So we can infer that p
in our original declaration has type "reference to array of 3 pointer to int
". Magic!
Example 2: float (*(*(&e)[10])())[5]
This is a declaration T D
where (§8.3.4 Arrays):
T
-> float
D
-> (*(*(&e)[10])())[5]
D
is of the form:
D1 [
constant-expressionopt ]
attribute-specifier-seqopt
where D1
is (*(*(&e)[10])())
. This means T D1
is of the form float (*(*(&e)[10])())
which has type "reference to array of 10 pointer to function of () returning pointer to float" (which you work out by applying §8.3/6 and then §8.3.1 Pointers and so on). Everything before the float
is the derived-declarator-type-list. So we can infer that p
in our original declaration has type "reference to array of 10 pointer to function of () returning pointer to array of 5 float". Magic again!