c ++ 0x: устранение неоднозначности между определением функции с последующим пустым объявлением и простым объявлением - PullRequest
15 голосов
/ 11 августа 2011

У меня проблема с тем, чтобы обернуть голову вокруг кажущейся неоднозначности в спецификации c ++ 0x, см. Также: http://www.nongnu.org/hcb/

Предположим, у нас есть код

void foo() {};

Лично я интерпретирую код как function-definition, за которым следует empty-declaration. Но, глядя на спецификацию грамматики, я бы сказал, что это так же легко можно интерпретировать как simple-declaration, который является частью block-declaration и, следовательно, упоминается раньше в списке declaration ...

Вот мое объяснение того, как это можно проанализировать как простое объявление:

void foo() {};"

-> Простое объявление

void

-> decl-спецификатор-seq -> decl-спецификатор -> тип-спецификатор -> трейлинг-тип- спецификатор -> простой тип-спецификатор

foo() {}

-> список объявлений init -> список объявлений init

foo()

-> декларатор -> декларатор ptr -> декларатор noptr

foo

-> идентификатор объявления -> ...

()

-> параметры и квалификаторы

{} 

-> initializer -> braced-init-list

Так что это должно быть возможно проанализировать как простое объявление.

Мне сказали, что 6.8 спецификации должны быть использованы для устранения неоднозначности этого случая, но я не совсем понимаю, почему. Является ли simple-declaration expression-statement, поскольку оно заканчивается ;?

1 Ответ

9 голосов
/ 11 августа 2011

Я думаю, что вы правы.Это двусмысленность, и я не знаю ни одного абзаца, который бы разрешал это в спецификации.

В спецификации C ++ 0x есть и другие неоднозначности, которые явно не разрешены, но (надеюсь) будут реализованы прямым способом компиляторами.Например, следующее может быть проанализировано как определение вложенного класса B, так и определение безымянного битового поля, имеющего размер 0 базового типа struct B.Последняя интерпретация сделает программу недействительной).

struct C { constexpr operator int() { return 0; } }; 
struct A { struct B : C { }; };

Другой пример

struct A {
  // is 0 a 'brace-or-equal-initializer' or a 'pure-specifier'?
  virtual void f() = 0;
};

Недавно Clang пришлось исправить следующее, потому что он ошибся (он проанализировал его как инициализацию переменной f вместо созданияфункция чистая).

typedef void T();
struct B : A {
  // B::f overrides A::f
  T f = 0;
};
...