В стандарте, что такое "производный-декларатор-тип"?

В разных местах стандарта С++ (С++ 11) объявления описываются в терминах списка производных-деклараторов. Я изучаю ссылки rvalue, и использование этого термина имеет решающее значение в этом контексте (§8.3.2):

В объявлении T D, где D имеет одну из форм     & attribute-specifier-seq opt D1
    && атрибут-specifier-seq opt D1 и тип идентификатора в объявлении T D1 "имя-производный-декларатор-type-list T", тогда тип идентификатора D "ссылка на тип производного-декларатора-типа для T."

К сожалению, категория "производный-декларатор-тип" никогда не определяется в стандарте. (Я просмотрел каждое использование слова "производное", и, кроме того, это возможно подтверждено здесь и .)

Потому что "выведенный-декларатор-тип-список" выделен курсивом, я предполагаю, что он относится к категории, а не к переменной label, такой как T (и, следовательно, я не согласен с Doug Оценка Gwyn во второй ссылке, которую я только что сказал, что "мы могли бы использовать X вместо" type-declarator-type-list ").

Что такое определение типа производного-декларатора в стандарте С++ 11?

Ответ 1

Он определяется прямо там и тогда. Это способ переносить все, что доходит до T до следующего типа, похожее на:

<some stuff> T
<some stuff> reference to T

Это как раз то, что доходит до T в типе T D1.

Например, если у вас есть объявление int& (*const * p)[30], T - int, D - & (*const * p)[30] и D1 - (*const * p)[30]. Тип T D1 - это "указатель на const указатель на массив из 30 int". Итак, согласно правилу, указанному вами, тип p является "указателем на указатель const на массив из 30 ссылок на int".

Конечно, это выражение затем запрещено в §3.4.2/5:

Не должно быть ссылок на ссылки, нет массивов ссылок и ссылок на ссылки.

Я думаю, что неформальная терминология, являющаяся производным списком типов деклараторов, исходит из стандартного определения C производного типа (аналогичного составному типу в С++):

Любое число производных типов может быть построено из объекта, функции и неполными типами:

  • Тип массива [...]
  • Тип структуры [...]
  • Тип объединения [...]
  • Тип функции [...]
  • Тип указателя [...]

В ответ на комментарии: похоже, вы путаетесь между типом и декларатором. Например, если int* p является декларатором, то тип p является "указателем на int". Тип выражается в виде этих англоязычных предложений.

Пример 1: int *(&p)[30]

Это объявление T D где (§8.3.1 Указатели):

  • Tint
  • D*(&p)[3]

D имеет вид:

* attribute-specifier-seq opt cv-qualifier-seq optD1

где D1 - (&p)[3]. Это означает, что T D1 имеет вид int (&p)[3], который имеет тип "ссылка на массив из 3 int" (вы рекурсивно выполняете это, следуя шагу, используя §8.3.4 Массивы и т.д.). Все, что находится перед int, является списком типов производных-деклараторов. Таким образом, мы можем заключить, что p в нашем исходном объявлении имеет тип "ссылка на массив из 3 указателей на int". Магия!

Пример 2: float (*(*(&e)[10])())[5]

Это объявление T D где (§8.3.4 Массивы):

  • Tfloat
  • D(*(*(&e)[10])())[5]

D имеет вид:

D1 [ константное выражение opt] attribute-specifier-seq opt

где D1 - (*(*(&e)[10])()). Это означает, что T D1 имеет вид float (*(*(&e)[10])()), который имеет тип "ссылка на массив из 10 указателей на функцию(), возвращающую указатель на float" (который вы разрабатываете, применяя § 8.3/6, а затем §8.3.1 указатели и так далее). Все, что находится перед float, является списком типов производных-деклараторов. Таким образом, мы можем заключить, что p в нашем исходном объявлении имеет тип "ссылка на массив из 10 указателей на функцию(), возвращающую указатель на массив из 5 float". Магия снова!