Open abeimler opened 1 month ago
The reason std::array<bool, N>
was originally used was due to constexpr
-ness that std::bitset
lacked/lacks.
Later the requirement of StructuralType was also added.
Overall it would be better to use bits instead of bytes if it meets all the "fixed_container" requirements.
Your fork seems to have the necessary requirements on bit_set
. It seems quite a bit different from the original version though, perhaps forked long ago?
Performance seems to be an on-par for access, and construction favors the smaller one. I wouldn't be surprised if some things are slower given the access patterns, but the footprint is for sure much smaller (at least for EnumSet
). I was wondering, is space the limiting factor in your application? EnumSet
is cheap given that it doesn't even store the enum keys, and EnumMap
is the same and is probably dominated by the values.
Are there any cons in always using bit_set in EnumSet?
The reason std::array<bool, N> was originally used was due to constexpr-ness that std::bitset lacked/lacks.
I figure that's why I start using xstd::bit_set, but switched later to EnumSet
(more speaking indexes and stronger typing etc.)
It seems quite a bit different from the original version though, perhaps forked long ago?
Yea I forked it years ago and update it from time to time, but some C++23 features (or other things) broke my build, so I rolled back. (older versions works fine for me)
Are there any cons in always using bit_set in EnumSet?
Right now it works for me, but the most operations I do are insert
, erase
and contains
.
The other thing is serialization, it can break, depending on how the bits/bools are stored. _(It also can have a smaller footprint storing uint32_t
bitset vs. array of bools)_
But for backwards-compatibility I just store the size, for-each the EnumSet
and store the values.
I was experimenting with sizes and alignment to keep my structs as small as possible and feel like EnumSet
(and EnumMap
?) gets a bit bloated.
For example... Without bit_set:
struct MyGameComponent {
EnumSet<Status> statuses; // Size: 48, Align: 8 (38 enums)
EnumSet<CanDoAction> can_do_actions; // Size: 32, Align: 8 (18 enums)
}
struct BattleStats {
EnumMap<Attributes, int32_t> base_stats; // Size: 48 (7 enums)
};
With bit_set
struct MyGameComponent {
EnumSet<Status> statuses; // Size: 16, Align: 8 (38 enums)
EnumSet<CanDoAction> can_do_actions; // Size: 16, Align: 8 (18 enums)
}
struct BattleStats {
EnumMap<Attributes, int32_t> base_stats; // Size: 40 (7 enums)
};
(size is also always the same, which can be nice.)
In my fork, I used the MACRO USE_BIT_SET_FOR_ENUM_SET
to enable the bit_set array_set
s, maybe split the different impl. and types into it's own classes or use template arguments to setup the option EnumSet
, BitsetEnumSet
, EnumMap
, EnumMapWithBitsetKeys
, ... (or something like that).template<..., EnumSetOption::UseBitsetForArraySet> ...
IMHO adding a (constexpr
-able & fixed) bit_set
in general can be a nice addition for this library and CAN be re-used in EnumSet
.
Hello, I was experimenting with
bit_set
in my own fork, replaced the internalstd::array<bool>
members withbit_set
._(Right know I'm using
bit_set
, I needed a more "modern"bit_set
with fixed length andconstexpr
)_1. Using
bit_set
asarray_set_
in myEnumSet
:2. Using
bit_set
asarray_set_
in myEnumMap
My main goal was to reduce the memory-foot-print, but the best thing I can do was
sizeof
and benchmark for speed :)EnumMap (random access)
Without
USE_BIT_SET_IN_ENUM_MAP
(std::array<bool>
)With
USE_BIT_SET_IN_ENUM_MAP
(bit_set
)EnumSet (random access)
Without
USE_BIT_SET_FOR_ENUM_SET
(std::array<bool>
)With
USE_BIT_SET_FOR_ENUM_SET
(bit_set
)EnumMap (construct)
Without
USE_BIT_SET_IN_ENUM_MAP
(std::array<bool>
)With
USE_BIT_SET_IN_ENUM_MAP
(bit_set
)_I guess the more
key
s an Enum has, the larger thestd::array
gets ... withbit_set
it's more limited._