REVERSE13 Telegram 691
Привет, сегодня будет лайтовый пост, про union.

Многие говорят про современный С++, никогда не используйте union, используйте variant/optional.

1) И если мы говорим об использовании в виде:
some_unsigned flag;
union { types... };

это безусловно так.
Хотя visit может быть менее оптимален чем ручной switch, но это проблема имплементации (несмотря на то что конкретно этот баг пофикшен, общее поведение не изменилось, что на мой взгляд весьма печально, единственную полноценную имплементацию этой идеи я видел в msvc stl)

Но что насчёт других применений union, где это не так?
2) Наверное первое что приходит в голову это type punning (union { unsigned, float }, чтобы посмотреть на битики float), в C это можно, но в C++ это UB.
Вероятно причина в том что если можно взять помимо мутабельной ссылки, ещё хотя бы одну любую ссылку, можно очень легко получить UB из-за aliasing-а:
void foo(A&, B&)
union { A a; B b; } x;
foo(x.a, x.b);

(Возможно в Rust это не проблема из-за borrow чекера?)
Другая возможная причина во взаимодействии с битовыми полями.
Резюмируя в C++ можно использовать только memcpy, или bitcast (до сих пор нет в apple libc++, учитывая что оно появилось в llvm libc++ 14, подозреваю будет в apple libc++ 16)

3) Два других менее очевидных применения это ленивый вызов конструктора и ранний вызов деструктора.
В обоих случаях можно использовать optional, но он увеличивает sizeof вашего класса, и не позволяет убрать conditional jmp из ленивого конструктора и сделать настоящий деструктор тривиальным (также убрав из него conditional jmp и вызов настоящего деструктора).

В YACLib мы этим пользуемся в паре мест, это в части бенчмарков дает нам выигрыш в 5-10%.
Сам же ленивый вызов конструктора нужен потому что у нас нет результата не запущенной функции.
А ранний вызов деструктора нужен чтобы разрушить функтор (например лямбду с захватом каких-то локов) сразу после того как она была вызвана.

В Rust кстати есть MaybeUninit специально для этого

4) variant не позволяет использовать SoA вместо AoS для флага, в случае же с union это вполне возможно, иногда полезно, и удобно если типы тривиальны.

5) Вместо aligned_storage_t или alignas(...) std::byte[...] (первое кстати задеприкейтили так как убогое).
На это есть несколько причин, во-первых это банально красивее и удобнее (нет нужды постоянно делать reinterpret_cast)
Во-вторых, по крайне мере до недавнего времени (не знаю можно ли сейчас) placement new нельзя было использовать в constexpr контексте, поэтому если вы хотели написать variant/optional<constexpr_allowed_type> вам нужно было в имплементации variant/optional использовать union

На этом вроде все, что вспомнилось, пишите если я что-то забыл!

А ещё я думаю по большей части это применимо и в других языках, например таких как Rust (но я не знаю их достаточно, поэтому не гарантирую)
👍10



tgoop.com/reverse13/691
Create:
Last Update:

Привет, сегодня будет лайтовый пост, про union.

Многие говорят про современный С++, никогда не используйте union, используйте variant/optional.

1) И если мы говорим об использовании в виде:
some_unsigned flag;
union { types... };

это безусловно так.
Хотя visit может быть менее оптимален чем ручной switch, но это проблема имплементации (несмотря на то что конкретно этот баг пофикшен, общее поведение не изменилось, что на мой взгляд весьма печально, единственную полноценную имплементацию этой идеи я видел в msvc stl)

Но что насчёт других применений union, где это не так?
2) Наверное первое что приходит в голову это type punning (union { unsigned, float }, чтобы посмотреть на битики float), в C это можно, но в C++ это UB.
Вероятно причина в том что если можно взять помимо мутабельной ссылки, ещё хотя бы одну любую ссылку, можно очень легко получить UB из-за aliasing-а:
void foo(A&, B&)
union { A a; B b; } x;
foo(x.a, x.b);

(Возможно в Rust это не проблема из-за borrow чекера?)
Другая возможная причина во взаимодействии с битовыми полями.
Резюмируя в C++ можно использовать только memcpy, или bitcast (до сих пор нет в apple libc++, учитывая что оно появилось в llvm libc++ 14, подозреваю будет в apple libc++ 16)

3) Два других менее очевидных применения это ленивый вызов конструктора и ранний вызов деструктора.
В обоих случаях можно использовать optional, но он увеличивает sizeof вашего класса, и не позволяет убрать conditional jmp из ленивого конструктора и сделать настоящий деструктор тривиальным (также убрав из него conditional jmp и вызов настоящего деструктора).

В YACLib мы этим пользуемся в паре мест, это в части бенчмарков дает нам выигрыш в 5-10%.
Сам же ленивый вызов конструктора нужен потому что у нас нет результата не запущенной функции.
А ранний вызов деструктора нужен чтобы разрушить функтор (например лямбду с захватом каких-то локов) сразу после того как она была вызвана.

В Rust кстати есть MaybeUninit специально для этого

4) variant не позволяет использовать SoA вместо AoS для флага, в случае же с union это вполне возможно, иногда полезно, и удобно если типы тривиальны.

5) Вместо aligned_storage_t или alignas(...) std::byte[...] (первое кстати задеприкейтили так как убогое).
На это есть несколько причин, во-первых это банально красивее и удобнее (нет нужды постоянно делать reinterpret_cast)
Во-вторых, по крайне мере до недавнего времени (не знаю можно ли сейчас) placement new нельзя было использовать в constexpr контексте, поэтому если вы хотели написать variant/optional<constexpr_allowed_type> вам нужно было в имплементации variant/optional использовать union

На этом вроде все, что вспомнилось, пишите если я что-то забыл!

А ещё я думаю по большей части это применимо и в других языках, например таких как Rust (но я не знаю их достаточно, поэтому не гарантирую)

BY Loser story


Share with your friend now:
tgoop.com/reverse13/691

View MORE
Open in Telegram


Telegram News

Date: |

Joined by Telegram's representative in Brazil, Alan Campos, Perekopsky noted the platform was unable to cater to some of the TSE requests due to the company's operational setup. But Perekopsky added that these requests could be studied for future implementation. In handing down the sentence yesterday, deputy judge Peter Hui Shiu-keung of the district court said that even if Ng did not post the messages, he cannot shirk responsibility as the owner and administrator of such a big group for allowing these messages that incite illegal behaviors to exist. Matt Hussey, editorial director of NEAR Protocol (and former editor-in-chief of Decrypt) responded to the news of the Telegram group with “#meIRL.” During a meeting with the president of the Supreme Electoral Court (TSE) on June 6, Telegram's Vice President Ilya Perekopsky announced the initiatives. According to the executive, Brazil is the first country in the world where Telegram is introducing the features, which could be expanded to other countries facing threats to democracy through the dissemination of false content. When choosing the right name for your Telegram channel, use the language of your target audience. The name must sum up the essence of your channel in 1-3 words. If you’re planning to expand your Telegram audience, it makes sense to incorporate keywords into your name.
from us


Telegram Loser story
FROM American