С++ 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;
};