In my entity component system I track and query which components each entity has using a bit mask.
// Thanks to Shafik Yaghmour for the macro fix
#define BIT(x) (static_cast<std::uint64_t>(1) << x)
enum class components : std::uint64_t
{
foo = BIT( 0),
bar = BIT( 1),
// Many more omitted
baz = BIT(63)
};
// Operator | is used to build a mask of components. Some entities
// have dozens of components.
auto mask = components::foo | components::bar | components::baz
// Do something with the entity if it has the requisite components.
if ( entity->has_components( mask ) ) { ... }
I've hit the 64 bit limit of the enumeration. Can a C++ enumeration (portably) be made bigger than 64 bits?
Update 1: I'm aware of std::bitset
, but I can't create a mask like auto mask = std::bitset<128>{ components::foo, components::baz }
because std::bitset
doesn't have a constructor that takes a std::initializer_list
. If your answer tells me to use std::bitset
please demonstrate this usage or similar.
Update 2: I hacked up a function to create a std::bitset
from a std::initializer_list
:
enum class components : std::size_t
{
foo,
bar,
baz,
count
};
template< typename enumeration, std::size_t bit_count = static_cast< std::size_t >( enumeration::count ) >
std::bitset< bit_count > make_bitset(std::initializer_list< enumeration > list)
{
assert(list.size() <= bit_count);
std::bitset< bit_count > bs{};
for (const auto i : list)
{
bs.set(static_cast< std::size_t >(i));
}
return bs;
}
// Which can create the mask like so:
auto mask = make_bitset< components >( {components::foo, components::baz} );