In lesson 16.9 -- Array indexing and length using enumerators, we discussed arrays and enumerations.
Now that we have constexpr std::array
in our toolkit, we’re going to continue that discussion and show a few additional tricks.
Using static assert to ensure the proper number of array initializers
When initializing a constexpr std::array
using CTAD, the compiler will deduce how long the array should be from the number of initializers. If less initializers are provided than there should be, the array will be shorter than expected, and indexing it can lead to undefined behavior.
For example:
Whenever the number of initializers in a constexpr std::array
can be reasonably sanity checked, you can do so using a static assert:
That way, if you add a new enumerator later but forget to add a corresponding initializer to testScores
, the program will fail to compile.
You can also use a static assert to ensure two different constexpr std::array
have the same length.
Using constexpr arrays for better enumeration input and output
In lesson 13.5 -- Introduction to overloading the I/O operators, we covered a few ways to input and output the names of enumerators. To assist in this task, we had helper functions that converted an enumerator to a string and vice-versa. These functions each had their own (duplicate) set of string literals, and we had to specifically code logic to check each:
This means that if we were to add a new enumerator, we’d have to remember to update these functions.
Let’s improve these functions a bit. In cases where the value of our enumerators start at 0 and proceed sequentially (which is true for most enumerations), we can use an array to hold the name of each enumerator.
This allows us to do two things:
- Index the array using the enumerator’s value to get the name of that enumerator.
- Use a loop to iterate through all of the names, and be able to correlate a name back to the enumerator based on index.
This prints:
Your shirt is blue Enter a new color: red Your shirt is now red
Range-based for-loops and enumerations
Occasionally we run across situations where it would be useful to iterate through the enumerators of an enumeration. While we can do this using a for-loop with an integer index, this is likely to require a lot of static casting of the integer index to our enumeration type.
Unfortunately, range-based for-loops won’t allow you to iterate over the enumerators of an enumeration:
There are many creative solutions for this. Since we can use a range-based for-loop on an array, one of the most straightforward solutions is to create a constexpr std::array
containing each of our enumerators, and then iterate over that. This method only works if the enumerators have unique values.
In the above example, since the element type of Color::types
is Color::Type
, variable c
will be deduced as a Color::Type
, which is exactly what we want!
This prints:
black red blue
Quiz time
Define a namespace named Animal
. Inside it, define an enum containing the following animals: chicken, dog, cat, elephant, duck, and snake. Also create a struct named Data
to store each animal’s name, number of legs, and the sound it makes. Create a std::array
of Data and fill out a Data element for each animal.
Ask the user to enter the name of an animal. If the name does not match the name of one of our animals, tell them so. Otherwise, print the data for that animal. Then print the data for all of the other animals that didn’t match their input.
For example:
Enter an animal: dog A dog has 4 legs and says woof. Here is the data for the rest of the animals: A chicken has 2 legs and says cluck. A cat has 4 legs and says meow. A elephant has 4 legs and says pawoo. A duck has 2 legs and says quack. A snake has 0 legs and says hissss.
Enter an animal: frog That animal couldn't be found. Here is the data for the rest of the animals: A chicken has 2 legs and says cluck. A dog has 4 legs and says woof. A cat has 4 legs and says meow. A elephant has 4 legs and says pawoo. A duck has 2 legs and says quack. A snake has 0 legs and says hissss.
Question #1