1

I have a C++ application where I want to use an array that is initialized on its declaration. The problem, though, is that the number of items is not fixed in the "normal" way, but it's based on a "counter" number inside a enum:

//"Normal way"
void myMethod()
{    
    bool myArray[3] = { false, false, false };
    //...
}

//My way
//In .hpp
enum MyEnum
{
    Item1,
    Item2,
    ...,

    MyEnumCount
}

//In .cpp
void myMethod()
{    
    bool myArray[MyEnumCount] = { false, false, false };
    //...
}

One situation that might occur while developing is a change in the MyEnum definition, either by increasing or decreasing the number of items on it. The idea is that, in case this happens, the code would automatically adapt itself to the new enum, without having to manually go to parts of the code for specific editions. Is there a way to do this in that array initialization? Or in this specific case, I would have to manually change its initialization always when MyEnum is changed?

Edit: Thanks for the all the replies written so far. I'm editing my question because I think my example above mislead some users in providing an answer for the actual question that was made (which is, actually, slightly different from the code I want for my app).

Restating my question: how does one initialize an array on its declaration with the values he wants when the size of the array is determined by a enum value which may be edited during code development without having to re-write the initialization?

This means:

  • No reply that uses a for-loop or any such a method is a valid one, since I'm talking about initializing the array on its declaration, not further in the code.
  • Although my initial code took my array as being a static one, the question is actually universal, that is, independent on the array being static or not. So no reply that takes advantage of a array being static is valid. Of course that not being a static array would left opened the question about why not use a for loop or similar to to the initialization, but in that case the answer should only do a "switch case": "if you have such an array, the way of doing this is the fallowing; if you have another kind of array, then the way is this other".
  • The code example came with a bool array with only "false", but the situation is actually universal, that is, the array may be filled with only "true" or even a combination of "true" and "false" sorted by some algorithm or even may not be a boolean array after all, but a int or a char or whatever.
  • I'm talking about arrays, not vectors or any C++ container ;)

Since I made this edits, I'll wait till tomorrow for a complete answer and, if not, I'll made one with the answers you provided. Thanks!

Momergil
  • 2,213
  • 5
  • 29
  • 59
  • 4
    [The question originally had a `static` array.] In this case there's no need for the initialiser, since static `bool`s will be initialised to `false` by default. – RichieHindle Jun 25 '14 at 14:42
  • @RichieHindle ow, that is good news :) But what if it was not static or I don't want to initilize all of them with "false", but some with "false" and others with "true"? Of course, than I could use a for loop as ikegami suggested, but let's suppose my curiosity still stands for initializing the array in the declaration (I'll chage my question taking out that static to maintain the question) – Momergil Jun 25 '14 at 14:43
  • You might want to look into `std::bitset`. It allows you to easily set the n-th bit. (And also has a default initializer). – tillaert Jun 25 '14 at 14:44
  • Use `std::fill` or `std::fill_n`. – T.C. Jun 25 '14 at 14:44
  • The default initialisation is for the array `{}` followed by using algorithms like `std::fill` and `std::begin` and `std::end` offer you the best in terms of safety in spite of the changes in the array size. If you use `std::array` you could also just then use `std::array.fill()`. The original question did make use of a `static` array, so the default brace initialisation will take care of leaving the array is a sane state from the start. – Niall Jun 25 '14 at 15:06
  • For Boolean arrays, you should review the `std::bitset`. – Thomas Matthews Jun 25 '14 at 16:18

6 Answers6

4

It is simple to do by specifying an empty brace-init list

void myMethod()
{    
    static bool myArray[MyEnumCount] = {};
    //...
}

In this case all elements of the array will be initialized to false. As the array is static then you may even do not specify the initializer. It will be zero-initialized by the compiler itself.

Take into account that you could use std::array:

For example

void myMethod()
{    
    static array<bool, MyEnumCount> myArray = {};
    //...
}

In this case you could reassign the array using the brace-init list.

Shoe
  • 74,840
  • 36
  • 166
  • 272
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
2

The code you have there (with MyEnumCount) will work since the MyEnumCount is constant at compile time.

With respect to the initialisation, there are some options available to you;

static bool myArray[MyEnumCount] = {};

Or (if the value is something more complex

static bool myArray[MyEnumCount];
// some place safe...
for (auto it = std::begin(myArray); it != std::end(myArray), ++it) {
  *it = false;
}
Niall
  • 30,036
  • 10
  • 99
  • 142
2

If you want to initialize everything to false, use an empty list:

bool myArray[MyEnumCount] = {};

If you want to initialize everything to something else, use std::fill or std::fill_n:

bool myArray[MyEnumCount];
std::fill_n(myArray, MyEnumCount, true);
// or std::fill(myArray, myArray + MyEnumCount, true);
T.C.
  • 133,968
  • 17
  • 288
  • 421
1

If it wasn't static,

bool myArray[MyEnumCount];
for (int i=MyEnumCount; i--; )
   myArray[i] = false;
ikegami
  • 367,544
  • 15
  • 269
  • 518
  • 1
    thanks for the answer, but as mentioned above, the idea is not simply to initialize the array, but to do that on it's definition (so a for loop isn't acceptable). Not to mentioned I may not actually want to put only "false" inside the array. – Momergil Jun 25 '14 at 14:49
  • A loop is *required* by definition, whether it's `for` or hidden away (e.g. `std::fill_n`). – ikegami Jun 25 '14 at 15:00
  • 4
    @ikegami: What are you talking about? `bool myArray[MyEnumCount] = {};` – Lightness Races in Orbit Jun 25 '14 at 15:28
  • @Lightness Races in Orbit, What about `bool myArray[MyEnumCount] = {};`? Are you claiming that doesn't loop? No, if that works, that initializes all elements of `myArray`. – ikegami Jun 25 '14 at 16:07
  • 2
    How is that a loop?! Not everything that affects more than a single byte is "a loop". – Lightness Races in Orbit Jun 26 '14 at 02:56
  • @Lightness Races in Orbit, How is it not? A loop is a repeated action. Unless you are saying `bool myArray[MyEnumCount] = {};` only initializes one element? – ikegami Jun 26 '14 at 05:31
  • Not everything that affects more than a single byte is "a loop". – Lightness Races in Orbit Jun 26 '14 at 09:07
  • @Lightness Races in Orbit, Right. `a=1; b=2;` is not a loop. I never said it was. You can stop repeating that irrelevant comment. – ikegami Jun 26 '14 at 12:02
1

It's fine to use an initializer that doesn't specify enough values, and the remaining values will take the default for that type:

enum MyEnum
{
    Item1,
    Item2,
    Item3,

    MyEnumCount
};

//In .cpp
void myMethod()
{    
    bool myArray[MyEnumCount] = {false, true};  // The third will be false
    //...
}
RichieHindle
  • 272,464
  • 47
  • 358
  • 399
  • @RichieHidle thanks for the answer! It did brought something new to the discussion! But what if the enum is made smaller? :) Then in that case, the extra "false/true" would be writing outside the myArray's memory? – Momergil Jun 25 '14 at 16:49
  • If there are too many values in the initializer, you'll get a compiler error. – RichieHindle Jun 25 '14 at 21:58
1

Do you have to use arrays? or can you use standard containers? For example, with vectors this can be easily done:

static std::vector<bool> myArray(false, MyEnumCount);

but there might be some problems with this being a static array. You need to make sure when the array is being initialized that the variable MyEnumCount has been already defined. In your case, because the static array is inside a function, you just need to make sure it is called after the definition of the count, which probably is.

triple_r
  • 1,037
  • 1
  • 8
  • 21
  • thanks for the answer, but given its usage on my code, I would say that there is no reason to go after a far more "fat" implementation as a class (std::vector) instead of a more simpler, less memory user as an array. :) – Momergil Jun 25 '14 at 16:46
  • 1
    @Momergil Fair enough :-) Just as something to think about, `std::vector` can be very slim and not that bad, performance-wise, compared to native arrays. Check this discussion: [link](http://stackoverflow.com/questions/381621/using-arrays-or-stdvectors-in-c-whats-the-performance-gap). Using vector, or other containers suggested here in the comments, might help your initialization easier, so, worst case, if there wasn't a clever method using native arrays, don't shy away from using containers because of performance loss. It is not as bad as it seems :-) – triple_r Jun 25 '14 at 18:45
  • far enough :) Thanks for the reply! – Momergil Jun 25 '14 at 19:19
  • Remember that `std::vector` is not a container in C++, as opposed to any other `std::vector`. – Shoe Jun 26 '14 at 03:00