С++ 11 стандартное ref для разрешенных типов определений в спецификаторе типов?

В С++ 11 спецификатор типа включает спецификаторы классов и спецификаторы перечисления. (так называемые определения классов и определения перечислений)

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

Например:

struct C{} c;
// ok: types may be defined in the specifiers of a simple declaration

void f(struct S{});
// error: types may not be defined in parameter types

constexpr auto i = sizeof(enum E{});
// error: types may not be defined in ‘sizeof’ expressions

Где в стандарте он разделяет эти применения спецификаторов типов на те, где типы могут и не могут быть определены? Например, где правило, в котором указано, что типы не могут быть определены в выражении sizeof?

Ответ 1

Причина, по которой он не может быть найден в стандарте С++, заключается в том, что он фактически запрещен в дельтах из стандарта C.

В С .1.4 мы имеем следующее: Change: Types must be declared in declarations, not in expressions In C, a sizeof expression or cast expression may create a new type., которое показывает запрет, о котором идет речь.

Это явно вызывается в 7.1.6/3:

Как минимум один спецификатор типа, который не является cv-определителем, требуется в объявление, если оно объявляет конструктор, деструктор или функция преобразования .92 Тип-спецификатор-seq не должен определять класс или перечисление, если оно не отображается в идентификаторе типа alias-declaration (7.1.3), которая не является объявлением Шаблон-декларации.

где часть особого интереса состоит в том, что A type-specifier-seq shall not define a class or enumeration unless...

Ответ 2

Из N3797:

8.3.5/9 Типы не должны определяться в обратном или параметрическом типах. Тип параметра или возвращаемый тип для определения функции должен не быть неполным классом (возможно, с квалификацией cv), если только функция удаляется ( 8.4.3), или определение вложено в спецификацию участника для этого класса (включая определения в вложенных классах, определенных в класс).

Это блокирует определение новых типов в объявлении функции.

Следующие два являются другими угловыми случаями, не упомянутыми OP:

11.3/2 Класс не должен определяться в объявлении друга.

14.1/2 Типы не должны определяться в объявлении параметра шаблона.

Наконец, это предложение блокирует его в sizeof и в другом месте:

7.1.6/3 Тип-спецификатор-seq не должен определять класс или перечисление, если он не отображается в идентификаторе типа alias-declaration (7.1.3), которая не является объявлением объявления шаблона

Обратите внимание, что C не имеет этого ограничения (C.1.4)

Кроме того, в предыдущей версии стандарта С++ мы имели:

5.3.3p5 Типы не должны определяться в выражении sizeof

который я не могу найти в стандартных предложениях последней версии, и он избыточен под N3797, поскольку sizeof маршрут для определения типа в грамматике находится через type-specifier-seq и заблокирован 7.1.6/3:

sizeof(type-id)type-idtype-specifer-seqtype-specifierclass-specifier