С++ 0x: устранение двусмысленности между определением функции, за которой следует пустая декларация и простая декларация

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

Предположим, что мы имеем код

void foo() {};

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

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

void foo() {};"

- > простая декларация

void

- > decl-specifier-seq → decl-specifier → type-specifier → trailing-type- specifier → спецификатор простого типа

foo() {}

- > init declarator-list → init-declarator

foo()

- > declarator → ptr-declarator → noptr-declarator

foo

- > declarator-id → ...

()

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

{} 

- > initializer → braced-init-list

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

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

Ответы

Ответ 1

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

В спецификации С++ 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;
};

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

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