Хорошо поддерживаемая альтернатива союзам С++?

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

Существуют ли альтернативы union, которые могут хотя бы имитировать те же свойства?


person user1849534    schedule 25.11.2012    source источник
comment
@CodingMash - система, основанная на сигналах, такая как SDL, и типы хранения, которые можно разделить на части, как в классическом примере значений RGB.   -  person user1849534    schedule 25.11.2012
comment
Вы уверены, что понимаете, что вам нужно? Объединения — это очень старая функция C, которая полностью поддерживается всеми компиляторами C++. Неограниченные союзы — это изменение союзов, новое в C++11. Прочитайте включенное описание функции, связанное с этой таблицей по вашей ссылке.   -  person Alan    schedule 25.11.2012


Ответы (3)


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

В качестве альтернативы вы всегда можете использовать указатель void, указывающий на распределенную память с достаточным размером для самого большого члена. Недостатком является то, что вам потребуется явное приведение типов.

person Lie Ryan    schedule 25.11.2012

Одной из популярных альтернатив объединению является Boost.Variant.

Типы, которые вы используете в нем, должны быть копируемыми.

Обновление: C++17 представил std::variant. Его требования основаны на Boost.Variant. Он модернизирован с учетом особенностей C++17. Он не требует совместимости с компиляторами C++98 (такими как Boost). Он поставляется бесплатно со стандартной библиотекой. При наличии лучше использовать его как альтернативу союзам.

person Öö Tiib    schedule 25.11.2012
comment
шаблон слова звучит не очень хорошо в этом случае, когда мне просто нужно заархивировать типы и сделать их действительно компактными; это также боль при разработке и отладке шаблонов. Этот уровень абстракции может стоить мне больше, чем он может мне дать. - person user1849534; 25.11.2012
comment
Если вы хотите избежать шаблонов, вам нужно написать все необходимые приведения и проверку типов вручную. - person Öö Tiib; 25.11.2012
comment
@delnan У меня нет аллергии на шаблоны, проблема в том, что преимущество объединения заключается в том, что оно работает очень просто, вводя шаблоны, которые труднее всего отлаживать + другая библиотека, не похоже премиальный выбор... - person user1849534; 25.11.2012
comment
@ user1849534: Преимущество варианта boost в том, что он уже хорошо протестирован на ряде компиляторов, поэтому вы, возможно, переоцениваете объем тестирования и отладки, которые вам необходимо выполнить. - person Öö Tiib; 25.11.2012
comment
Шаблоны @user1849534 невероятно мощные и полезные, они значительно упрощают разработку и поддержку определенных функций по сравнению с альтернативами. Если вы так беспокоитесь о шаблонах, что думаете, что простой одноуровневый шаблон, подобный тому, который показал ybungalobill, приведет к непонятным ошибкам, которые вы видели в других местах, то вы просто недостаточно использовали шаблоны. - person bames53; 25.11.2012
comment
IME, боязнь шаблонов обычно связана с использованием контейнеров STL, которые действительно имеют страшные ошибки. Но простые ошибки шаблона, как правило, не так уж плохи. - person Lie Ryan; 25.11.2012

Вы всегда можете сделать по существу одно и то же, используя явное приведение типов:

struct YourUnion {
    char x[the size of your largest object];
    A &field1() { return *(A*)&x[0]; }
    int &field2() { return *(int*)&x[0]; }
};

YourUnion y;
new(&y.field1()) A(); // construct A
y.field1().~A(); // destruct A
y.field2() = 1;
// ...

(Это нулевые накладные расходы по сравнению, например, с Boost.Variant.)

EDIT: больше похоже на союз и без шаблонов.

person Yakov Galka    schedule 25.11.2012
comment
Вам нужно убедиться, что хранилище правильно выровнено. - person bames53; 25.11.2012
comment
@ user1849534: вам не нужно использовать шаблоны ... вы можете каждый раз писать приведение вручную. - person Yakov Galka; 25.11.2012
comment
@user1849534 user1849534 Почему вы хотите избегать шаблонов? - person bames53; 25.11.2012
comment
Если поддерживается, используйте std::aligned_storage. - person ipc; 25.11.2012
comment
@ybungalobill хорошо, это решение, но, чувак, я скучаю по старому доброму профсоюзному подходу ... - person user1849534; 25.11.2012
comment
@user1849534 user1849534 Если вы думаете, что простые шаблоны, подобные тому, который изначально показал ybungalobill, будут слишком сложными для отладки, то вам также следует опасаться неограниченных союзов; в отличие от большинства C++, вам нужно вручную управлять временем жизни членов, и если вы ошибетесь, компилятор не сообщит вам об этом, вы просто получите неопределенное поведение. - person bames53; 25.11.2012