Моя история начинается так же, как этот человек здесь:
Объединения в C ++ 11: конструктор по умолчанию, кажется, удален
Разрешение здесь (сейчас около трех лет) немного неудовлетворительно, потому что «копание в стандарте», которое автор сделал, привело к выводу, что поведение было таким, как описано в стандарте, но, к сожалению, цитата из Примечание , и они должны быть ненормативными (мне сказали). В любом случае, есть ссылка на старый отчет об ошибках в gcc, который, как утверждается, исправлен, и они также утверждают, что код компилируется в clang, однако у меня возникают проблемы (с таким же и похожим кодом). Вопрос сводится к тому, должен ли подобный объединению класс с инициализированным по умолчанию вариантом члена-члена компилироваться независимо от того, существует ли другой вариант-член (в том же наборе вариантов), который имеет нетривиальный конструктор.
struct X {
X() {} //non-trivial default constructor
};
struct U {
union {
X x;
int i{0}; //default member initializer
};
};
U u; //error: default constructor deleted
Это не удалось с -std=c++14
и -std=c++17
на gcc version 7.3.0 (Ubuntu 7.3.0-27ubuntu1~18.04)
, а также clang version 6.0.0-1ubuntu2
.
Кажется, в стандарте есть история изменений, и поэтому я изложу то, что нашел:
N3690 / N4140:
[12.1.4 / Конструкторы]
... Конструктор по умолчанию для класса X определяется как удаленный, если:
- X является объединяющим классом, в котором есть вариантный член с нетривиальным конструктором по умолчанию
[9.5.2 / Союзы] ...
[Заметка:
Если какой-либо элемент нестатических данных объединения имеет нетривиальное значение по умолчанию
конструктор (12.1), конструктор копирования (12.8), конструктор перемещения (12.8), оператор назначения копирования (12.8), перемещение
оператор присваивания (12.8) или деструктор (12.4), соответствующая функция-член объединения должна быть
предоставленный пользователем или он будет неявно удален (8.4.3) для объединения.
- конец примечания]
N4659 / N4727:
[15.1.5 / Конструкторы]
... Конструктор по умолчанию для класса X определяется как удаленный, если:
- X - это объединение, в котором есть вариантный член с нетривиальным конструктором по умолчанию, и ни у одного вариантного члена X нет инициализатора элемента по умолчанию
[12.3.3 / Союзы] ...
[Заметка:
Отсутствуют инициализаторы членов по умолчанию, если любой нестатический член данных объединения имеет нетривиальное значение по умолчанию
конструктор (12.1), конструктор копирования (12.8), конструктор перемещения (12.8), оператор назначения копирования (12.8), перемещение
оператор присваивания (12.8) или деструктор (12.4), соответствующая функция-член объединения должна быть
предоставленный пользователем или он будет неявно удален (8.4.3) для объединения.
- конец примечания]
В любом случае, кажется, что в какой-то момент этот код должен был потерпеть неудачу, но считалось, что он соответствует и что у gcc есть ошибка, и она была исправлена, но теперь она должна быть успешной, и это не так компилировать (у меня может не быть идеальной хронологии, было бы интересно узнать всю историю; выяснить это на шаг дальше, чем я хотел бы сделать), но я думаю, мне просто интересно, каково правильное поведение?