9

I have a question that is sort of a follow up to this:

Initializing default values in a struct

I've got a struct that's already got 17 bools, and a clear() method that sets them all to false. It's a long term project; the code could still be in use years from now and get added to. Is there a way to initialize all members that will extend automatically, so that someone adding new members to the struct doesn't need to remember to add them to the clear() method (other than a comment saying "please don't forget")?

This code base is not C++11 at this time, so I don't think I can initialize in the declaration.

The code is like this:

typedef struct {
    bool doThingA;
    bool doThingB;
    bool doThingC;
    bool doThingD;
    // etc for several more bools

    void clear() {
        doThingA = false;
        doThingB = false;
        doThingC = false;
        doThingD = false;
        // etc...
    }
} EnableFlags;
Community
  • 1
  • 1
  • 12
    Please find the person who taught you to say `typedef struct`, delete their phone number, unfriend them on Facebook and move at least two cities away from them. – Kerrek SB Nov 13 '15 at 17:51
  • 4
    Why not have `array`/`vector` or `bitset` ? – Jarod42 Nov 13 '15 at 17:51
  • 2
    You could use a `std::array` instead since it is a fixed size and you know the size automatically in `clear`. – Shafik Yaghmour Nov 13 '15 at 17:51
  • I'd strongly recommend an `std::bitset`: http://en.cppreference.com/w/cpp/utility/bitset – ApproachingDarknessFish Nov 13 '15 at 17:59
  • 1
    As a general note: Though you can probably find a technical solution to any problem, smart people tend to not create avoidable problems in first place. The smart solution here is: *"don't change your structs"*. i.e. design your classes to be stable, but extensible. See: [open-closed principle](https://en.wikipedia.org/wiki/Open/closed_principle). Also, if your struct has 17 members, there is probably [something wrong](https://en.wikipedia.org/wiki/KISS_principle) is going on. – Ivan Aksamentov - Drop Nov 13 '15 at 18:05
  • @KerrekSB, This can be useful when declaring a structure and pointer to this structure simultaneously. – Andrey Nasonov Nov 13 '15 at 22:44
  • 1
    @AndreyNasonov I guess you mean defining a type alias for pointer to struct, however that is a bad idea in the first place – M.M Nov 13 '15 at 23:21

3 Answers3

9
struct EnableFlags {
    bool doThingA;
    bool doThingB;
    bool doThingC;
    bool doThingD;
    // etc for several more bools

    void clear() {
        *this = EnableFlags();
    }
};

This will create a temporary with all members set to zero and then make *this a copy of it. So it sets all the members to zero, no matter how many there are.

This assumes that you haven't defined a default constructor that does something other than set all the flags to false. If you have no user-defined constructors then that assumption holds.

Since C++11 it's even simpler:

void clear() {
    *this = {};
}
Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
  • 2
    `*this = {};` is dangerous, as if the class has an assignment operator taking `int`, then that is preferred to the copy-assignment operator. [See here for full example](http://stackoverflow.com/questions/33511641/overload-resolution-assignment-of-empty-braces) – M.M Nov 13 '15 at 23:24
  • 1
    also, `*this = EnableFlags();` does default-initialization in C++98, but value-initialization in C++03. I mention this in case OP is using C++98 (for example, 32-bit Borland / Embarcadero compilers) – M.M Nov 13 '15 at 23:42
  • 1
    Anyone using C++98 rather than C++03 deserves whatever they get. It's 2015, if your compiler is nearly old enough to legally drink alcohol then you have a problem that should be solved by changing compiler, not by compromising your code. – Jonathan Wakely Nov 14 '15 at 01:11
2

One option is to use a static assertion about the size of the structure inside the clear function.

First determine the current size of the struct. Let's say it's 68. Then, add this:

void clear()
{
  BOOST_STATIC_ASSERT(sizeof(EnableFlags) == 68 && "You seem to have added a data member. Clear it before changing the number 68 to match current struct size!!");

  // the rest as before ...
}

I've used Boost's static assertion macro, but you can use any other one you want, or roll out your own.

With such an assertion, the code will fail to compile when the size of the structure changes. It's not a catch-all solution, but does provide a safeguard.

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
1

Just use objetcs.

So you can use a 'for' loop to check in a std::vector if their values are false or true.

So you don't have your futurs co-workers put the "false" value each time they create a new boolean variable.

Structures are inapropriates here.

Madz
  • 287
  • 3
  • 14