Союзы в С++ 11: конструктор по умолчанию, кажется, удален

Я пытаюсь понять, как профсоюзы были расширены С++ 11. Одна вещь, которая изменилась, - это возможность использовать теперь нестатические элементы данных с нетривиальными специальными функциями-членами. Из cppreference.com

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

Я пытаюсь выполнить следующий код:

struct X
{
    ~X() {};
};

union U
{
    X x;
    ~U() {};
};

int main()
{
    U s1{};  // works, probably aggregate initialization
    U s2;    // DOES NOT compile, why?
}

Live on Coliru

Здесь X (который используется как член данных объединения) имеет предоставленный пользователем деструктор, поэтому деструктор объединения по умолчанию удаляется. Поэтому я предоставляю это явно. Однако код не компилируется с ошибкой

note: 'U:: U()' неявно удаляется, потому что определение по умолчанию будет плохо сформировано:

Код компилируется, если я удаляю последнюю строку U s2;.

Вопрос Что здесь происходит? Почему U s1{}; компилируется, но U s2; нет? Является ли по умолчанию ctor союза помеченным как удаленное (если да, почему?!), и в первом случае мы имеем только агрегатную инициализацию? Обратите внимание, что если я предоставляю U(){}; // not U() = default;, код компилируется (но не если я предоставляю только ctor X).

ИЗМЕНИТЬ

После перехода в стандарт (N4527):

Союзы: 9.5/2 [class.union]

[Примечание: если какой-либо нестатический член данных объединения имеет нетривиальный конструктор по умолчанию (12.1), конструктор копирования (12.8), конструктор перемещения (12.8), оператор назначения копирования (12.8), оператор присваивания перемещения ( 12.8) или деструктор (12.4), соответствующая членская функция объединения должна быть предоставлена ​​пользователем или она будет неявно удалена (8.4.3) для объединения. -endnote]

похоже, что это ошибка gcc (теперь сообщается здесь). Код компилируется на clang и gcc 4.8.2 или ранее, он разбивается на gcc4.9 и более поздние версии (спасибо @T.C. для указания).

Компилятор: g++ 5.3, -std=c++11.

Ответ 1

Цитата cppreference неясно. Случается, что если ANY memeber из union определяет ЛЮБОЙ из тех нетривиальных специальных функций-членов, то ВСЕ из них будут удалены по умолчанию в объединении.

Итак, поскольку у вас есть нетривиальный деструктор для X, конструктор по умолчанию U удален.

Ответ 2

X не является типом типа, поскольку он не является тривиально гибким, поскольку он имеет деструктор Также U не является типом элемента.

U s2; попробуйте вызвать обработчик по умолчанию, который удален, поэтому ошибка

U s1 {}; использовать член мудрую инициализацию и не называть какой-либо costructor

В объединении с членом non pod стандартная команда объединения по объему удаляется, потому что она будет вызывать конструктор затрат по умолчанию для членов, т.е. компилятор не знает, какой член вызовет конструктор затрат по умолчанию

 Union XX{
   string m1; 
   vector <int> m2;
}

defaultructructor из XX не может вызывать конструктор затрат по умолчанию m1 AND m2, поэтому он удален