Является ли "int (x), 1;" двусмысленное утверждение?

void f(int x) {
    int (x), 1;
}

Clang компилирует его, GCC нет. Какой компилятор прав?

Ответы

Ответ 1

IMO, формулировка в [stmt.ambig] достаточно ясна для этого:

Оператор выражения с преобразованием явного типа в стиле функции как его самое левое подвыражение может быть неотличимым от объявления, где первый декларатор начинается с (. В этих случаях оператор является объявлением.

[Примечание: Если оператор не может синтаксически быть объявлением, нет никакой двусмысленности, поэтому это правило не применяется. Весь анализ, возможно, потребуется изучить, чтобы определить, так ли это.

В формулировке говорится о целом (выражение). Ваш оператор не может быть проанализирован как объявление, потому что lexeme 1 не является грамматически не декларатором. Нет никакой двусмысленности: он выглядел бы двусмысленным, если бы мы смотрели исключительно на int(x), но стандарт явно явно отрицает, что если какой-либо префикс оператора анализирует как объявление, весь оператор считается потенциальным объявлением.

Фактически, основные эксперты имели очень похожие обсуждения в 2002 году над основной проблемой 340 --- Я выделил важные биты. Здесь, опять же, мы имеем предполагаемое объявление, которое содержит несовместимую подконструкцию.

Рассмотрим следующую программу:

struct Point   {
  Point(int){}   
};
struct Lattice    {
  Lattice(Point, Point, int){}   
};
int main(void)   {
  int a, b;
  Lattice latt(Point(a), Point(b), 3);   /* Line X */   
} 

Проблема касается строки, помеченной /* Line X */, которая является двусмысленной объявления для объекта или функции. Предложение о том, что регулирует эту двусмысленность - это пункт 8.2 [dcl.ambig.res], который гласит:

Неоднозначность, возникающая из-за сходства между функциональным стилем   cast и декларация, упомянутая в 6.8 [stmt.ambig] [..]

В соответствии с этим пунктом есть два возможные интерпретации объявления в строке X:

  • Объявление latt объявляет функцию с возвращаемым значением введите Lattice и возьмите три аргумента. Тип первых двух аргументы Point, и за каждым из этих аргументов следует имя параметра в резервных круглых скобках. Тип третьего аргумент не может быть определен, потому что он является буквальным.. Это будет приводят к синтаксической ошибке.
  • Объявление решетки объявляет объект, потому что другой вариант (объявление функции) приведет к ошибка синтаксиса. Обратите внимание, что последнее предложение перед "[Примечание:" не является много помощи, потому что обе опции являются декларациями.

Стив Адамчик: несколько человек ответили на это сообщение comp.std.С++ говорят, что они не видели проблемы.

Оригинал плакат ответил:

Я не могу ничего сделать, но соглашусь с вашей аргументацией. Таким образом, существует только одна правильная интерпретация пункта 8.2 [dcl.ambig.res] пункт 1, но я должен сказать, что с некоторой переформулировкой пункт может быть сделано намного яснее, как явно заявить, что весь декларация должна быть принята во внимание и что декларации функций предпочтительнее над объявлениями объектов.

Я хотел бы предложить следующее в качестве замены текущего пункт 8.2 [dcl.ambig.res], пункт 1:

Неоднозначность, возникающая из-за сходства между личным стилем   и декларация, упомянутая в 6.8 [stmt.ambig] [...]

Рабочая группа сочла, что нынешняя формулировка достаточно ясна.