Наиболее неприятный синтаксический анализ и указатель косвенного обращения / разыменования

Минимальный код:

struct A {
A(int = 0) {}
};

int i = 0, *p = &i;
int* foo () { return p; }

int main () {
A(); // calls `A::A(int=0)`
A(i);  // calls `A::A(int=0)`

A(*p); // <--- (1) same as local `A *p;`
{
A((*p));   // <--- (2) same as local `A *p;`
}
A (*foo());  // <--- (3) ??
{
A ((*foo()));  // <--- (4) ??
}
}

Ожидал хотя бы A((*p)) будет ссылаться A::A(int=0), Даже положить несколько скобок вокруг *p, трактует заявление как A *p;,
То же самое относится и к foo родственное утверждение, где конструктор A::A(int=0) не называется.
Вот демонстрация.

Вопрос:

  1. Почему даже (2) и (4) рассматриваются как декларации?
  2. Что такое описания foo в утверждениях (3) и (4)?

4

Решение

При синтаксическом анализе конструкции, которая может быть либо объявлением, либо выражением — известным как двусмысленность синтаксического анализа — стандарт говорит: «Решение состоит в том, чтобы рассмотреть любую конструкцию, которая может быть объявлением декларацией».

Оба (2) и (4) являются действительными объявлениями, поэтому они должны быть проанализированы как объявления. Оба (3) и (4) объявляют функцию foo типа A*() aka «функция, не принимающая параметров, возвращающая указатель на A«

6.8 Ambiguity resolution [stmt.ambig]

В грамматике существует двусмысленность, связанная с выражениями-операторами и объявлениями: выражение-выражение с явным преобразованием типа в стиле функции (5.2.3) в качестве крайнего левого подвыражения может быть неотличимо от объявления, где первый декларатор начинается с ((. В этих случаях заявление является декларацией. [Примечание: Чтобы устранить неоднозначность, может потребоваться проверка всего утверждения, чтобы определить, является ли оно выражением-выражением или объявлением. Это устраняет неоднозначность многих примеров. [Пример: предполагая, что T является спецификатором простого типа (7.1.5),

T(a)->m = 7; // expression-statement
T(a)++; //expression-statement
T(a,5)<<c; //expression-statement
T(*d)(int); //declaration
T(e)[5]; //declaration
T(f) = { 1, 2 }; // declaration
T(*g)(double(3)); // declaration

В последнем примере выше, g, который является указателем на T, инициализируется как double (3). Это, конечно, неосознанно по смысловым причинам, но это не влияет на синтаксический анализ. — конец примера]

8.2 Ambiguity resolution [dcl.ambig.res]

Неоднозначность, возникающая из-за сходства между приведением стиля функции и объявлением, упомянутым в 6.8, также может происходить в контексте объявления. В этом контексте выбор делается между объявлением функции с избыточным набором скобок вокруг имени параметра и объявлением объекта со стилем функции, приведенным в качестве инициализатора. Как и в случае двусмысленности, упомянутой в 6.8, решение состоит в том, чтобы рассмотреть любую конструкцию, которая может быть декларацией декларацией. [Примечание: объявление может быть явно устранено неоднозначностью с помощью приведения типа, не являющегося функцией, с помощью = для указания инициализации или путем удаления лишних скобок вокруг имени параметра. ] [Пример:

struct S {
S(int);
};

void foo(double a)
{
S w(int(a)); // function declaration
S x(int()); // function declaration
S y((int)a); // object declaration
S z = int(a); // object declaration
}

— конец примера]

1

Другие решения

Почему даже (2) и (4) рассматриваются как декларации?

Скобки в объявлениях могут использоваться для изменения порядка ассоциации в объявлениях и, возможно, для изменения значения конструкции от объявления к выражению. Они имеют такой же приоритет, как [] и группа слева направо.

Например:

int*a[1];   // brackets have higher precedence - this is an array of pointers
int(*a)[1]; // pointer to an array

Теперь, если вы считаете, A*p; а также A(*p); круглые скобки здесь излишни, потому что они не изменили способ синтаксического анализа. Добавление большего количества из них ничего не меняет — это все еще действительная декларация.

Каково описание foo в утверждениях (3) и (4)?

Декларации такие же, как A* foo();

1

По вопросам рекламы [email protected]