Вопрос:

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

c++ syntax expression language-lawyer variable-declaration

412 просмотра

1 ответ

17524 Репутация автора

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

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

Автор: geza Источник Размещён: 08.11.2017 10:10

Ответы (1)


17 плюса

54057 Репутация автора

Решение

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

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

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

Формулировка говорит о целом (выражении) утверждении. Ваше утверждение не может быть проанализировано как объявление, потому что лексема 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], который гласит:

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

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

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

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

Оригинальный постер ответил:

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

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

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

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

Автор: Columbo Размещён: 08.11.2017 11:57
Вопросы из категории :
32x32