Подтвердить что ты не робот

Законно ли определять безымянную структуру?

Является ли следующий код законным?:

struct
{
    int  x;
};

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

Хотя это бесполезно, я не вижу проблем с этим. Просто еще один кусок кода, который можно скомпилировать, а затем полностью оптимизировать.

Тем не менее, в реальном мире результат сильно отличается от моих ожиданий:

GCC 8.3 сообщает об ошибке:

ошибка: абстрактный декларатор '<безымянная структура>' используется как объявление

Clang 8.0.0 также сообщает об ошибке:

ошибка: анонимные структуры и классы должны быть членами класса
предупреждение: объявление ничего не объявляет [-Wmissing-декларации]

Только MSVC 2017 не видит проблем с таким источником.

Итак, вопрос: кто прав? Есть ли соответствующая цитата из Стандарта, которая явно запрещает такие декларации?

Редактировать:
В проекте используется С++ 11. Но сообщения об ошибках одинаковы для С++ 98, С++ 11 и С++ 17.

4b9b3361

Ответ 1

Нет, это не разрешено. GCC и Clang правы.

Согласно [dcl.dcl]/3 (7 объявлений) в N3337 (окончательный вариант С++ 11), объявление класса должно вводиться в программе под одним именем. Например, следующие недопустимы:

enum { };
typedef class { }; 

(Примечание: это не уникально для С++ 11. В N4140 (окончательный вариант С++ 14) это [dcl.dcl]/5 (7 объявлений). В N4659 (окончательный вариант С++ 17) это [dcl.dcl]/5 (10 деклараций).)

Ответ 2

Это запрещено грамматикой языка при описании типов классов.

class-specifier:
    class-head { member-specificationopt }
class-head:
    class-key attribute-specifier-seqopt class-head-name class-virt-specifieropt base-clauseopt
    class-key attribute-specifier-seqopt base-clauseopt
class-head-name:
    nested-name-specifieropt class-name
class-virt-specifier:
    final
class-key:
    class
    struct
    union

Все, что необязательно, четко обозначено как таковое. Имя класса не является обязательным.

Ответ 3

Да, это разрешено, если вы создаете экземпляр объекта этой структуры:

struct
{
    int  x;
} obj;

obj является экземпляром безымянной структуры.