|
Boost : |
Subject: Re: [boost] Is there any interest in type-safe container of bool flags with noexcept guarantees?
From: Roman Orlov (compmaniak_at_[hidden])
Date: 2017-03-22 16:02:05
On 21.03.2017 21:23, Steven Watanabe via Boost wrote:
>
> what's wrong with
> struct animal {
> bool eats_meat : 1;
> bool eats_grass : 1;
> bool has_tail : 1;
> };
>
There are several reasons I don't like that approach
While declaring a variable of type 'animal' you should always keep in
mind to initialize it with empty initializer
animal a1; // bit fields are not initialized
animal a2{}; // now it's ok, bits are set to zeros
When you want to initialize some fields (eats_grass, has_tail) you have
to write several lines of code
animal a1{};
a1.eats_grass = 1;
a1.has_tail = 1;
Of course, it can be done in one line with initializer list
animal a1{0, 1, 1};
But we don't write a code ones, we are about to support it for a long
time. One day we decided to add a new bit field to structure
struct animal {
bool can_fly : 1; // yeah, somebody puts it on the first position
bool eats_meat : 1;
bool eats_grass : 1;
bool has_tail : 1;
};
What will happen with all of list initializers? There will be bugs we
can't detect at compile time.
animal a1{0, 1, 1}; // now it doesn't work properly
We have to find all of such initializers and rewrite them
animal a1{0, 0, 1, 1};
To prevent this I propose to abstract from strict ordering and use
typed entities
animal a1{flag<eats_grass>{1}, flag<has_tail>{1}};
And what about bitwise operations on plain structures? While working
with bool properties conjunction and disjunction are needed fairly
often. For each structure you'll have to implement them manually.
Of course it's better to have it out of the box
auto a1 = animal{flag<eats_gass>{1}} | animal{flag<eats_meat>{1}};
Sometimes it's needed to test that all flags are set or at least one.
And again for each structure you'll have to implement it manually.
It's better to have these functions in container
auto a1 = animal{flag<eats_gass>{1}};
assert( (!a1.all()) );
assert( (!a1.any<eats_meat, has_tail>()) ); // with some syntax sugar
Managing typed entities allows you to test common properties of
semantically different entities. For example:
class p1;
class p2;
class p3;
class p4;
typedef typed_flags<p1, p2, p3> a; // has p3 property
typedef typed_flags<p3, p4> b; // has p3 property too
template<typename T, typename... Args>
bool test_p(Args&&... args) {
return (... && args.template test<T>());
}
// test p3 property from a and b
test_p<p3>(a{flag<p3>{1}}, b{flag<p3>{1}});
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk