Detailed enumeration of C++11 strong types

  • 2020-11-03 22:32:19
  • OfStack

1. Defects of traditional enumeration types

An enumeration type is a user-defined construct type in C/C++, which is a collection of user-defined enumeration constants. Enumeration values correspond to integer values, starting at 0 by default. For example, define an enumeration type for a descriptive gender.


enum Gender{Male,Female};

The enumeration value Male is assigned 0 by default by the compiler and Female is assigned 1. There are several problems with the design of traditional enumeration types.

(1) Enumeration value with the same scope will report a redefinition error. In traditional C++, enumeration constants are exposed in the same scope of 1 layer. If there are two different enumeration types in the same scope of 1, but the enumeration constants with the same name will also report compilation errors, such as:


enum Fruits{Apple,Tomato,Orange};
enum Vegetables{Cucumber,Tomato,Pepper}; // Compile the report Tomato Redefinition error 

The inclusion of Tomato enumeration constants with the same name in both fruit and vegetable enumerations causes a compilation error. Because enum is a non-strongly scoped type, enumeration constants can be accessed directly, in a very different way than C++ named namespace, class/struct, and union must be accessed by "name :: member name".

(2) Because enumeration types are designed as "aliases" of constant values, enumeration constants can always be implicitly converted to integers, and users cannot define types for enumeration constants.

(3) Enumeration constants occupy storage space and the symbolic uncertainty. The C++ standard states that the "base type" on which C++ enumerations are based is specifically implemented by the compiler, which leads to the problem of uncertainty in the base type of members of an enumerated type, especially the problem of notation, i.e. Consider the following example:


enum A{A1=1,A2=2,ABig=0xFFFFFFFFU};
enum B{B1=1,B2=2,BBig=0xFFFFFFFFFUL};

int main()
{
	cout<<sizeof(A1)<<endl;	//4
	cout<<ABig<<endl;		//4294967295
	cout<<sizeof(B1)<<endl;	//8
	cout<<BBig<<endl;		//68719476735
}

The above output results are compiled by USING g++ on Linux platform, and the output results in VC++ (VS2017) are 4, -1, 4 and -1 respectively. You can see that different compilers have different implementations for the width and symbol of the integer type of the enumerated constants. GNU C++ USES integers of different widths and symbols depending on the type of the enumeration value, while VC++ always represents the enumeration constant as a signed int.

C++11 introduces strong type enumerations to solve these problems.

2. Strongly typed enumeration

Non-strongly scoped types, which allow implicit conversions to integers, enumeration constants occupying storage space, and symbolic uncertainty are all disadvantages of enumeration classes. To address these shortcomings, C++11 introduced a new enumeration type, strongly typed enumeration (ES49en-ES50en enum).

Strongly typed enumerations are declared using the enum class syntax:


enum class Enumeration{VAL1,VAL2,VAL3=100,VAL4};

Strongly-typed enumerations have several advantages:
(1) Strong scope: The name of a strong type enumeration member will not be output to its parent scope, so the compilation of an enumeration member with the same name of different enumeration type definitions will not report a redefinition error. When enumerators of the enumeration type are then used, the scope must be specified, such as Enum::VAL1, and VAL1 alone is no longer meaningful;
(2) Conversion restriction: Values of strongly typed enumeration members cannot be implicitly converted to and from integers. For example, Enumeration::VAL4==10; Triggers a compilation error;
(3) The underlying type can be specified. The default underlying type for strongly typed enumerations is int, but the underlying type can also be explicitly specified. This is done by adding ":type" to the enumeration name, where type can be any integer other than wchar_t. Such as:


enum class Type:char{Low,Middle,High};

Note:
(1) When declaring strong type enumeration, the keyword enum class or enum can be used. In fact, there is no grammatical difference between enum struct and enum class.
(2) Since the strongly typed enumeration is strongly scoped, the anonymous enum class may not be able to do anything. The following code will report a compilation error:


enum class{General,Light,Medium,Heavy}weapon;
int main()
{
weapon=Medium; // Compile error 
bool b=weapon == weapon::Medium; // Compile error 
return 0;
}

Of course, we can still use decltype to get the type for anonymous strongly-typed enumerations and then use it, but doing so may violate the original purpose of strong typed enumerations for anonymity.

3.C++11 extensions to traditional enumeration types

Traditional enumeration Type C++11 extends the traditional enumeration type to match the strong type enumeration introduced by C++11.
(1) The underlying base type can be appended with ":type" after the enumeration name, where type can be any integer other than wchar_t, such as:


enum Type:char{Low,Middle,High};

(2) In C++11, members of an enumerated type can be valid within the scope of the enumerated type. Such as:


enum Type{Low, Middle, High };
Type type1 = Middle;
Type type2 = Type::Middle;

Middle and Type::Middle are both legal forms of use.

The above is a detailed explanation of C++11 strong type enumeration details, more information about c++ enumeration please pay attention to other related articles on this site!


Related articles: