Вопрос о том, какой тип объявления заключен в круглые скобки

#c #c 17 #language-lawyer #declaration

#c #c 17 #язык-юрист #объявление

Вопрос:

В разделе dcl.meaning говорится:

Таким образом, объявление определенного идентификатора имеет вид
T D
, где T имеет вид attribute-specifier-seq opt decl-specifier-seq, а D является декларатором. Ниже приведена рекурсивная процедура для определения типа, указанного для содержащегося идентификатора декларатора с помощью такого объявления.

[пуля 6] В объявлении T D, где D имеет форму
( D1 )
, тип содержащегося идентификатора декларатора совпадает с типом содержащегося идентификатора декларатора в объявлении
T D1
Круглые скобки не изменяют тип встроенного идентификатора декларатора, но они могут изменять привязку сложных деклараторов.

Однако рассмотрим приведенный ниже код

 int main(){
  int* (ptr) = nullptr;
}
  

В моем примере (ptr) соответствует форме (D1) , однако это не декларатор, полный декларатор в моем примере *ptr . Согласно пуле, упомянутой выше, (D1) обозначает D , D является декларатором объявления (обратите внимание на выделенную часть), то есть (D1) должен быть декларатором объявления. Только форма int (*ptr) соответствует тому, о чем говорится в пуле 6. Кажется, что маркер 6 не охватывает пример int* (ptr) . Итак, как интерпретировать такой случай? каков тип такого декларатора-id( int* (ptr) ). Если я неправильно понимаю пункт 6, как правильно понять пункт 6? Или пуля 6 является дефектом формулировки, которая игнорирует такой случай?

Ответ №1:

Вы должны перейти к следующему разделу. Пункт 6 — это всего лишь один случай, который здесь неприменим, потому что ваше объявление не имеет формы T (D1) . Он имеет вид T D with T = int и D = *(ptr) . D = *D1 (сопоставление здесь с D1 = (ptr) ) обрабатывается [dcl.ptr] :

В объявлении, T D где D , имеет вид

 *attribute-specifier-seq_opt cv-qualifier-seq_opt D1  

и тип идентификатора в объявлении T D1 равен « derived-declarator-type-list T «, тогда тип идентификатора D является «производным-декларатором-типом-списком cv-квалификатором-следующим указателем на T «. cv-квалификаторы применяются к указателю, а не к объекту, на который указано. Аналогично, необязательный атрибут-спецификатор-seq относится к указателю, а не к объекту, на который указано.

Итак, чтобы узнать, что int *(ptr) означает, мы сначала рассмотрим, что int (ptr) означает. Теперь вступает в действие ваша цитата в [dcl.meaning] , в которой говорится, что это то же самое, что int ptr . Итак, int (ptr) было бы объявить идентификатор ptr как тип int . Затем, согласно правилу, которое я процитировал, int *(ptr) объявляется ptr как указатель на int .

Комментарии:

1. да, вы правы. [dcl.meaning] не намеревается охватывать int *(ptr) . Другими словами, (D1) должен быть полный декларатор, что является случаем, описанным [dcl.meaning]

2. Еще один вопрос. почему предложение не является where D is the form (D1) ? В моем понимании, where D has the form (D1) означает, что *(ptr) это также ситуация, о которой говорится в предложении. Принимается (ptr) как (D1) , принимается *(ptr) как D , где D включает (D1) .

3. Это просто не то, что означают эти слова. *(ptr) не имеет формы (не соответствует шаблону) (D1) . Точка. *(ptr) имеет синтаксический подтерм, который имеет эту форму (соответствует этому шаблону), в частности (ptr) , но (ptr) не *(ptr) , и это просто не имеет значения, если какое-либо другое правило не делает это важным.