In this video, we'll look at the structure or syntax of an enumeration.
If you've ever seen an enumeration before, you may be confused by the structure shown here.
That's because many elements of an enumeration are optional.
So often you'll see enumerations without names, types or attributes.
You'll notice that we have also omitted attributes from this structure.
That's because attributes are a separate topic altogether and apply to more than just enumerations in
this section will only be covering the basics of enumerations.
So topics such as attributes won't be included.
With that being said, let's take a look at the elements of an enumeration that will be using.
First we have the enumeration key.
This defines the beginning of the enumeration as well as its scope.
We'll cover the different types of enumeration scopes in detail soon, but for now, just know that
the enumeration can be either scoped or scoped regardless of the scope.
And enumeration will always start with the keyword enum.
The next part of an enumeration is its name naming is optional for scoped enumerations but can be useful
for imposing type restrictions on variables that you want to be able to enumeration type.
This is similar to what we saw in the last video where we imposed a type restriction on the state variable
by declaring it as a state enumeration type.
If we had not named the state enumeration, we would not been able to do that.
We'll see soon why this is the case.
Next, we have a colon followed by a type specified where the specified type serves as the fixed underlying
type of the enumerations enumerators.
Specifying the underlying type is optional but can be used to reduce the amount of space and enumeration
takes up in memory or to increase the accuracy of any calculations involving the enumerator values.
The last part of the enumeration is a set of curly braces, and this is the Enumerations Enumerator
List.
This is where we define the names and integral values of the enumerators belonging to the enumeration.
This can be done explicitly or implicitly.
That's it.
Now let's look at a simple enumeration to see these elements in action.
This is about as simple of an enumeration as we can get.
It has no name, no fixed underlying type, and has three enumerators red, green and blue.
You'll notice that none of the enumerators have been initialized.
This is because the compiler could do this for us if the first enumerator has no initialization.
The compiler was signed at a value of zero for all other enumerators without initialize, as the compiler
will assign the value of the previous enumerator plus one.
This is known as implicit initialization.
Of course, we might not always want the integral values assigned by the compiler, so we can always
explicitly assign them ourselves.
In some cases, we may want to assign certain enumerator specific values and not care what the others
are assigned.
In cases like these, we can explicitly assign certain enumerators the values we want, and have the
compiler implicitly assign values to the others.
This is known as explicit implicit initialization.
Now let's take a look at the enumerations underlying type in more detail.
If the underlying type of an enumeration is not fixed, the compiler assigns the first integral type
that it's able to hold the enumerations entire value range.
These integral types are listed on the right and rank order with signs given preference over unsigned.
The sizes or widths of these integral types depends on the system being used, but for this example,
we'll use the C++ minimum standard, which are reflected by the values listed.
Now with this knowledge, can you tell what underlying type the compiler will assign to our simple enumeration?
It might help to look at the minimum binary representation of our numerator values, assuming a signed
bit is used.
We could see that each of the numerators can be represented by three bits, and so the first integral
type that is able to hold all three bits is INT, since it has a width of 16 bits.
Now what if we explicitly initialize the numerator blue with the value negative three 2769?
Obviously the underlying type will need to be signed since it must be able to hold negative values.
But can we tell whether it will be an int a long or a long long?
Let's take a look at the minimum binary representation of our numerator values.
Again, the numerator is red and green, require three bit representation and blue a 32 bit representation
because the underlying type must be able to hold all the numerator values.
The compiler will base its selection on the largest required bit representation in this case blue.
And so the compiler will assign the enumeration the underlying type of law.
In some cases we may want to fix an enumerations underlying type for the purposes of saving memory or
increasing the accuracy of calculations involving enumerator values.
This can be accomplished by placing a colon and the fixed underlying data type directly before the Enumerators
Enumeration list.
C++ has types such as Unit eight, UT 16 and so forth that allow us to specify the exact number of bits
that we require.
If we try to fix an underlying type that cannot hold the enumerations entire range.
The compiler will throw an error.
Now let's look at the naming of an enumeration in more detail.
Nameless enumerations are often referred to as anonymous enumerations.
Because anonymous enumerations have no name.
It's not possible to declare variables of that enumeration type.
The best we can do is to clear a variable as the underlying type of the enumeration.
But this means that while the variable can be assigned to the enumerators, it can also be assigned
any value belonging to the underlying type.
Because of this, we say that anonymous enumerations provide no type safety.
In the case of the anonymous enumeration containing the numerators red, green and blue.
If we want the variable, my color to be assigned one of these enumerators, we must declare it as the
underlying type of the enumeration in this case int.
But this means that while it can be assigned red, green and blue, it can also be assigned any integer
value.
Oftentimes we want the variables assignment to be restricted to only the numerators of an enumeration.
As we saw earlier with the rocket launch example.
This can be quite important.
So to accomplish this, we can give an enumeration a meaningful name that represents its enumerators.
By providing a name, we're defining the enumeration as a unique type that can only assume its enumerated
values.
Because of this, we say that the enumeration provides type safety.
As good design practice.
The name given to an enumeration should form an is a relationship with its enumerators.
In this case, color is a good name for the enumeration.
Since red is a color, green is a color and blue is a color.
By giving the enumeration the name color, we have defined a unique type of that name, which can only
assume the values of red, green and blue.
As such, we can declare the variable my color as a color type, thus restricting its assignment to
only red, green or blue.
And that's it.
Almost everything you need to know about an enumeration structure.
The only thing that's left to cover other scopes and all the things we can do with them.
Now let's head over to the next video to learn what scoped enumerations are and how we can use them.