|
Boost : |
Subject: Re: [boost] Is there any interest in type-safe container of bool flags with noexcept guarantees?
From: Richard Hodges (hodges.r_at_[hidden])
Date: 2017-03-22 17:14:08
I agree that bitfields are not the way to go. They suffer from a number of
deficiencies - not least that each bit is *not a separate object* so they
are problematic i multithreaded environments. They also of course carry no
type information.
However, I am struggling to see how the proposed class is any more useful
than a std::tuple classes that support a bool conversion operator.
Can you demonstrate a use case where a tuple is inadequate?
On 22 March 2017 at 17:02, Roman Orlov via Boost <boost_at_[hidden]>
wrote:
> 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}});
>
>
> _______________________________________________
> Unsubscribe & other changes: http://lists.boost.org/mailman
> /listinfo.cgi/boost
>
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk