The text previously defined Scope as "the location in a program where a specific name is visible and accessible." Scope is a property of any programming element a programmer names: variables, functions, structures, classes, enumerations, etc. The name becomes a symbol in the program. The compiler component saves the symbol in its symbol table, mapping the symbol name to the corresponding element's address in the case of a definition. Programmers typically specify basic enumerations in global scope, giving their symbolic constants global scope. However, global scope often causes problems.
Global-Scope Conflicts
The Scope Resolution Operator
We first encountered the scope resolution operator during the introduction of C++'s I/O system. Two adjacent semicolons, without any intervening space, form it. While it can operate either as a unary or binary operator, the latter is the most frequently used version. The binary version is left associative, processing its operands from left to right.
Programmers narrow a feature's scope by enclosing it in a container: a structure, namespace, or class. In this sense, enumerations are containers holding a set of symbolic constants. C++ also allows the nesting of one container in another. In conjunction with a container, the operator permits programmers to manage the scope of a programming element. The left-hand operand names a scoping container, while the right-hand operand names the final feature or a nested container. In the following example, programmers use it to select elements specified in a specific enumeration or structure.
Embedded Enumerations
The conflicting enumerations, radiation and function, each have a well-defined meaning within a given context:
A hurricane named Gamma in the Gulf of Mexico during the 2020 Atlantic hurricane season
When a radioactive isotope decays, it generally emits one of three kinds of radiation: alpha or beta particles or gamma rays.
The gamma function generalizes the factorial function, extending the range over most real numbers.
These observations suggest that including GAMMA in multiple enumerations and using them in the same program should be valid. But specifying the various GAMMA elements in the same (global) scope causes the conflict. We can limit their scope, thereby eliminating the conflict, by embedding the enumerations inside a structure and extending the access syntax. (The following examples demonstrate syntax but don't otherwise solve a "real" problem.)
int main()
{
int h1 = GAMMA;
int h2 = ::GAMMA;
Decay pu = { "Pu-239", Decay::radiation::GAMMA, 2.41e4 };
int i2 = pu.mode;
cout << pu.mode << endl;
int i1 = Decay::radiation::GAMMA;
int m = Math::GAMMA;
return 0;
}
(a)
(b)
Embedding an enumeration in a structure. Programs can only access or use enumerations embedded in structures through the structure name. In this example, the hurricane specification remains in global scope, but radiation and function are specified inside different structures. Although each enumeration has an element named GAMMA, their specifications are in different scopes and don't conflict.
Programmers may specify any number of enumerations in global scope if the identifiers (the optional specification name and the elements) are unique within the specifying scope. radiation and function are specified inside the Decay and function structures, restricting the scope of each one to the specifying structure. Programmers typically put the enumeration and structure specifications in a header file, but they must occur before the program uses the name.
When accessing a global enumeration, the unary scope resolution operator is optional but is required when accessing an embedded enumeration. The binary version is evaluated from left to right, binding its right-hand operand to the scope defined by its left-hand operand. Reading in evaluation order, left to right, we can "decode" the expression Decay::radiation::GAMMA as follows:
Decay::radiation means the name radiation is declared or specified in the Decay structure.
radiation::GAMMA means the name GAMMA is declared or specified in radiation enumeration.
The GAMMA specified in radiation is independent of and distinct from the GAMMA declared in the other enumerations.
Although C provides both enumerations and structures, it does not have the scope resolution operator and, therefore, cannot support nested enumerations.
Scoped Enumerations
Scoped enumerations are similar in appearance and simplicity to the initial, conflicting example - nevertheless, a simple syntax update made in 2011 resolves the conflict. Adding one of two existing keywords to the enumeration specification creates a new, named scope and binds the enumeration specification to it. Programmers can choose either enum class or enum struct; both versions have the same effect, but the first is preferred.