
On 03/22/17 19:02, Roman Orlov via Boost 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};
Frankly, all the above problems are solved with constructors. The only real problem I see with the struct approach is that it's lacking expressiveness. From this declaration: animal a1{0, 1, 1}; it is difficult to immediately say what the value of has_tail will be. It would be better if we had named field initialization, like in C, but alas. Usually, I solve this problem with std::bitset with an enum providing names for the flags. enum animal_traits { eats_meat, eats_grass, has_tail, _count }; typedef std::bitset< animal_traits::_count > animal; animal a1; // all traits are false a1[eats_grass] = 1; a1[has_tail] = 1; I think, this provides the necessary expressiveness and performance. I guess, your proposal provides better type safety than this solution, but I'm not sure the improvement is significant enough to outweigh the more complicated syntax. For example, one could write a slightly more complicated version of the above: enum animal_traits { eats_meat, eats_grass, has_tail, _count }; template< typename Enum, unsigned int Count > class typed_bitset : public std::bitset< Count > { public: bool operator[] (Enum idx) const { return std::bitset< Count >::operator[](idx); } }; typedef typed_bitset< animal_traits, animal_traits::_count > animal; animal a1; // all traits are false a1[eats_grass] = 1; a1[has_tail] = 1; a1[10] = 1; // error I suspect it would also be faster to compile.