2016-01-03 2 views
10

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

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

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

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 (который используется в качестве элемента данных объединения) имеет при условии пользователя деструктор, следовательно, деструктор объединение по умолчанию удаляется. Поэтому я предоставляю это явно. Тем не менее, код не компилировать с ошибкой

примечание: '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), соответствующий член func союз должен быть предоставлен пользователем или он будет неявно удален (8.4.3) для объединения. -endnote]

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

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

+1

[Clang] (http://coliru.stacked-crooked.com/a/b58a360400009fa9) вполне доволен этим кодом. На самом деле это похоже на ошибку GCC. –

+0

@ T.C. Да, я действительно видел это только после вашего комментария. Я сначала сделал впечатление, что clang также отклонил его, возможно, была проверена некоторая модифицированная версия. Отредактировал последнюю строку вопроса, спасибо. – vsoftco

+0

@ T.C. Я попытаюсь вникнуть в стандарт ... – vsoftco

ответ

2

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

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

+0

Спасибо, если это так, тогда это имеет смысл. И 'U s1 {};' работает, потому что мы используем агрегатную инициализацию, правильно? – vsoftco

+0

В основном, да. Правила C++ 11 позволяют вам иметь более сложные типы в союзах, но вам нужно управлять вызовом своих конструкторов и деструкторов вручную на основе любого тега типа, который вы используете в объекте/функции, управляющей объединением. Обычно это означает использование new/delete. –

+0

У вас есть предложение? Я не думаю, что это стандарт. –

1

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

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

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

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

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

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

+1

Согласитесь с вашим утверждением, но я не понял, почему конструктор по умолчанию удален. – vsoftco

+0

@vsoftco Я добавляю некоторое объяснение того, что, по моему мнению, appens – alangab

+0

Это может быть так, хотя я не вижу причин, по которым компилятор не может просто вызвать конструктор первого члена. Точно так же, как если бы вы выполняли 'XX x {" test "};', компилятор вызывает ctor 'm1', т. Е. Ctor первого члена. – vsoftco

Смежные вопросы