1

I have a struct of bools.
It contains no other data member but bool.

struct foo {
 bool b1 = false;
 bool b2 = false;
 bool b3 = false;
 // many more ...
};

Without using reflection or code generation,
I'm looking for an easy way to set them all to true, and then set them all to false.

Is it legal everywhere to memset them?

foo f;
memset(&f, true, sizeof f);
memset(&f, false, sizeof f);

As long as I guarantee the data members are always primitives, is this a safe and well-defined operation? If not, are there any other suggestions for ensuring that a large set booleans (more of which may be added in the future), can be consistently all be set to true/false. I would also like to keep them false by default. The reason I want to set them all to true occasionally, is that its useful for unit tests and code coverage.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
Trevor Hickey
  • 36,288
  • 32
  • 162
  • 271
  • 1
    Closely related [Is it safe to memset bool to 0?](https://stackoverflow.com/q/33380742/1708801) – Shafik Yaghmour Nov 27 '18 at 20:30
  • 1
    This is what happens when you choose wrong data structure - that should be a vector of bools. – Slava Nov 27 '18 at 20:30
  • related/dupe: https://stackoverflow.com/questions/53339268/what-trait-concept-can-guarantee-memsetting-an-object-is-well-defined – NathanOliver Nov 27 '18 at 20:31
  • 2
    @Slava Maybe a `std::array` of bools instead. `vector` can be not fun to play with. – NathanOliver Nov 27 '18 at 20:31
  • Remember, there may be padding between your `bool`s. – Jesper Juhl Nov 27 '18 at 20:35
  • If a type is not [POD](https://en.cppreference.com/w/cpp/types/is_pod) you cannot safely `memset` it. That's your criteria. – Jesper Juhl Nov 27 '18 at 20:37
  • 2
    @NathanOliver yes or even maybe `std::bitset`, depends on situation. Point is - `struct` with a lot of `bool` is probably the worst choice here. – Slava Nov 27 '18 at 20:44
  • 1
    `std::bitset` or flags would be much better. – Smit Ycyken Nov 27 '18 at 20:45
  • Yeah, that's good advice. These bool structs are derived from an IDL, so having simple types with identifier names leads to easier serialization for us. It's helpful to have specific identifiers that can be statically checked. If we were to use a container, none of the the indexes would have any names, and we would need to use enums or some kind of map key-- leading to potential run-time issues. I was thinking about a named tuple, where I could get the best of both worlds (names, and iterating), but I don't want to get too fancy if memset will suffice (Especially because of serialization). – Trevor Hickey Nov 28 '18 at 04:47

1 Answers1

3

Because the number of bools is known at compile time you can easily replace these structs with a bitset

struct foo {
    bool b1 = false;
    bool b2 = false;
    bool b3 = false;
};

Can simply become a bitset<3U>. This will allow you to use:

  • set to set all bits to true
  • reset to set all bits to false

The key problem with using memset for the boolean type is that:

The value of sizeof(bool) is implementation defined and might differ from 1

Thus it is implementation defined whether bools will be located at each byte of memory in foo as memset(&f, true, sizeof f) presumes.

Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
  • 1
    That's what I'm not sure about. Regardless of a bool's size, wouldn't the bools still be true as long as their values are non-zero? We are memsetting each byte in the struct. So all the bytes related to all the bools will be non-zero. The number of bytes that make up each bool seem unrelated. – Trevor Hickey Nov 28 '18 at 05:02
  • @TrevorHickey I'll make this a comment because it is purely speculation. Firstly, I believe that even `bool`s must be byte aligned. But I haven't searched the standard to confirm that. If a collection of `bool`s takes *less* space than 1 the `memset` doesn't work. Secondly, there is the question of whether `false` is *represented* as 0 internally. I don't believe that the standard requires that... Making the `memset` implementation defined. So again as stated in my answer, I believe the best that can be said of the `memset` is that it is implementation (universally?) defined. – Jonathan Mee Nov 28 '18 at 13:29