I was thinking about microoptimizing a function that returns 4 bools
by using an union of uint32_t and bool[4], and then doing the popcnt
instruction to see how many elements of the bool array are true.
That will cause undefined behavior because accessing an inactive member of the union violates the object lifetime rules. You probably want to use a std::bitset<4>
instead — it is designed for usage like this.
Note that std::bitset
cannot directly be constructed from several bool
s, you may have to compose an unsigned long long
first. Or you can use a helper function like this:
template <std::size_t N>
constexpr std::bitset<N> pack_bools(const bool (&arr)[N])
{
static_assert(N <= std::numeric_limits<unsigned long long>::digits);
unsigned long long num{0};
for (std::size_t i = 0; i < N; ++i) {
if (arr[i])
num += 1LL << i;
}
return std::bitset<N>{num};
}
usage:
pack_bools({true, false, true, false}); // for example
(test)
But I do not know if the standard guarantees that bool is represented
as number with only 1 bit set when true and 0 bits set when it is
false.
No, there's no guarantee like that. [basic.fundamental]/10:
Type bool
is a distinct type that has the same object
representation, value representation, and alignment requirements as an
implementation-defined unsigned integer type. The values of type
bool
are true
and false
. [ Note: There are no signed
,
unsigned
, short
, or long
bool
types or values. — end
note ]
There's no more guarantee about the value representation.
If the answer is no then I have a follow up question: if it is not
required is it required that representation is constant, e.g. if I
have a test that checks that true bool casted to uint_8t is 1(and 0
for false) does that this means that every representation of bools in
the program will behave the same.
No, there's no such guarantee either.