mirror of
https://github.com/isocpp/CppCoreGuidelines.git
synced 2025-12-17 12:44:42 +03:00
Update and extension of enumeration section
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
# <a name="main"></a>C++ Core Guidelines
|
# <a name="main"></a>C++ Core Guidelines
|
||||||
|
|
||||||
july 16, 2016
|
July 16, 2016
|
||||||
|
|
||||||
Editors:
|
Editors:
|
||||||
|
|
||||||
@@ -7018,15 +7018,16 @@ Enumerations are used to define sets of integer values and for defining types fo
|
|||||||
|
|
||||||
Enumeration rule summary:
|
Enumeration rule summary:
|
||||||
|
|
||||||
* [Enum.1: Prefer enums over macros](#Renum-macro)
|
* [Enum.1: Prefer enumerations over macros](#Renum-macro)
|
||||||
* [Enum.2: Use enumerations to represent sets of named constants](#Renum-set)
|
* [Enum.2: Use enumerations to represent sets of related named constants](#Renum-set)
|
||||||
* [Enum.3: Prefer class enums over "plain" enums](#Renum-class)
|
* [Enum.3: Prefer `enum class`es over "plain" `enum`s](#Renum-class)
|
||||||
* [Enum.4: Define operations on enumerations for safe and simple use](#Renum-oper)
|
* [Enum.4: Define operations on enumerations for safe and simple use](#Renum-oper)
|
||||||
* [Enum.5: Don't use `ALL_CAPS` for enumerators](#Renum-caps)
|
* [Enum.5: Don't use `ALL_CAPS` for enumerators](#Renum-caps)
|
||||||
* [Enum.6: Use unnamed enumerations for ???](#Renum-unnamed)
|
* [Enum.6: Avoid unnamed enumerations](#Renum-unnamed)
|
||||||
* ???
|
* [Enum.7: Specify the underlying type of an enumeration only when necessary](#Renum-underlying)
|
||||||
|
* [Enum.8: Specify enumerator values only when necessary](#Renum-value)
|
||||||
|
|
||||||
### <a name="Renum-macro"></a>Enum.1: Prefer enums over macros
|
### <a name="Renum-macro"></a>Enum.1: Prefer enumerations over macros
|
||||||
|
|
||||||
##### Reason
|
##### Reason
|
||||||
|
|
||||||
@@ -7057,23 +7058,47 @@ Instead use an `enum`:
|
|||||||
int webby = blue; // error: be specific
|
int webby = blue; // error: be specific
|
||||||
Webcolor webby = Webcolor::blue;
|
Webcolor webby = Webcolor::blue;
|
||||||
|
|
||||||
|
We used an `enum class` to avoid name clashes.
|
||||||
|
|
||||||
##### Enforcement
|
##### Enforcement
|
||||||
|
|
||||||
Flag macros that define integer values
|
Flag macros that define integer values.
|
||||||
|
|
||||||
### <a name="Renum-set"></a>Enum.2: Use enumerations to represent sets of named constants
|
|
||||||
|
### <a name="Renum-set"></a>Enum.2: Use enumerations to represent sets of related named constants
|
||||||
|
|
||||||
##### Reason
|
##### Reason
|
||||||
|
|
||||||
An enumeration shows the enumerators to be related and can be a named type
|
An enumeration shows the enumerators to be related and can be a named type.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
##### Example
|
##### Example
|
||||||
|
|
||||||
enum class Webcolor { red = 0xFF0000, green = 0x00FF00, blue = 0x0000FF };
|
enum class Webcolor { red = 0xFF0000, green = 0x00FF00, blue = 0x0000FF };
|
||||||
|
|
||||||
|
|
||||||
|
##### Note
|
||||||
|
|
||||||
|
Switching on an enumeration is common and the compiler can warn against unusual patterns of case labels. For example:
|
||||||
|
|
||||||
|
enum class Productinfo { red = 0, purple = 1, blue = 2 };
|
||||||
|
|
||||||
|
void print(Productinfo inf)
|
||||||
|
{
|
||||||
|
switch (inf) {
|
||||||
|
case Productinfo::red: cout << "red"; break;
|
||||||
|
case Productinfo::purple: cout << "purple"; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Such off-by-one switch`statements are often the results of an added enumerator and insufficient testing.
|
||||||
|
|
||||||
##### Enforcement
|
##### Enforcement
|
||||||
|
|
||||||
???
|
* Flag `switch`-statements where the `case`s cover most but not all enumerators of an enumeration.
|
||||||
|
* Flag `switch`-statements where the `case`s cover a few enumerators of an enumeration, but has no `default`.
|
||||||
|
|
||||||
|
|
||||||
### <a name="Renum-class"></a>Enum.3: Prefer class enums over "plain" enums
|
### <a name="Renum-class"></a>Enum.3: Prefer class enums over "plain" enums
|
||||||
|
|
||||||
@@ -7117,11 +7142,20 @@ Convenience of use and avoidance of errors.
|
|||||||
|
|
||||||
##### Example
|
##### Example
|
||||||
|
|
||||||
???
|
enum Day { mon, tue, wed, thu, fri, sat, sun };
|
||||||
|
|
||||||
|
Day operator++(Day& d)
|
||||||
|
{
|
||||||
|
return d==sun?mon:Day{++d};
|
||||||
|
}
|
||||||
|
|
||||||
|
Day today = sat;
|
||||||
|
Day tomorrow = ++today;
|
||||||
|
|
||||||
##### Enforcement
|
##### Enforcement
|
||||||
|
|
||||||
???
|
Flag repeated experssions cast back into a an enumeration.
|
||||||
|
|
||||||
|
|
||||||
### <a name="Renum-caps"></a>Enum.5: Don't use `ALL_CAPS` for enumerators
|
### <a name="Renum-caps"></a>Enum.5: Don't use `ALL_CAPS` for enumerators
|
||||||
|
|
||||||
@@ -7129,27 +7163,102 @@ Convenience of use and avoidance of errors.
|
|||||||
|
|
||||||
Avoid clashes with macros.
|
Avoid clashes with macros.
|
||||||
|
|
||||||
##### Example
|
##### Example, bad
|
||||||
|
|
||||||
???
|
// webcolors.h (third party header)
|
||||||
|
#define RED 0xFF0000
|
||||||
|
#define GREEN 0x00FF00
|
||||||
|
#define BLUE 0x0000FF
|
||||||
|
|
||||||
|
// productinfo.h
|
||||||
|
// The following define product subtypes based on color
|
||||||
|
|
||||||
|
enum class Productinfo { RED, PURPLE, BLUE }; // syntax error
|
||||||
|
|
||||||
##### Enforcement
|
##### Enforcement
|
||||||
|
|
||||||
???
|
Flag ALL_CAPS ennumerators.
|
||||||
|
|
||||||
### <a name="Renum-unnamed"></a>Enum.6: Use unnamed enumerations for ???
|
### <a name="Renum-unnamed"></a>Enum.6: Avoid unnamed enumerations
|
||||||
|
|
||||||
##### Reason
|
##### Reason
|
||||||
|
|
||||||
???
|
If you can't name an enumeration, the values are not related
|
||||||
|
|
||||||
##### Example
|
##### Example, bad
|
||||||
|
|
||||||
???
|
enum { red = 0x,FF0000, scale = 4, signed = 1 };
|
||||||
|
|
||||||
|
Such code is not uncommon in code written before there were convenient alternative ways of specifying integer constants.
|
||||||
|
|
||||||
|
##### Alternative
|
||||||
|
|
||||||
|
Use `constexpr` values instead. For example:
|
||||||
|
|
||||||
|
constexpr int red = 0x,FF0000;
|
||||||
|
constexpr short scale = 4;
|
||||||
|
constexpr bool signed = true;
|
||||||
|
|
||||||
##### Enforcement
|
##### Enforcement
|
||||||
|
|
||||||
???
|
Flag unnamed enumerations.
|
||||||
|
|
||||||
|
|
||||||
|
### <a name="Renum-underlying"></a>Enum.7: Specify the underlying type of an enumeration only when necessary
|
||||||
|
|
||||||
|
##### Reason
|
||||||
|
|
||||||
|
The default is the easiest to read and write.
|
||||||
|
`int` is the default integer type.
|
||||||
|
`int` is compatible with C `enum`s.
|
||||||
|
|
||||||
|
##### Example
|
||||||
|
|
||||||
|
enum class Direction : char { n,s,e,w, ne, nw, se, sw }; // underlying type saves space
|
||||||
|
|
||||||
|
enum class Webcolor : int { red = 0xFF0000, green = 0x00FF00, blue = 0x0000FF }; // underlying type is redundant
|
||||||
|
|
||||||
|
##### Note
|
||||||
|
|
||||||
|
Specifying the underlying type is necessary in forward declations of enumerations:
|
||||||
|
|
||||||
|
enum Flags : char;
|
||||||
|
|
||||||
|
void f(Flags);
|
||||||
|
|
||||||
|
// ....
|
||||||
|
|
||||||
|
enum flags : char { /* ... */ };
|
||||||
|
|
||||||
|
|
||||||
|
##### Enforcement
|
||||||
|
|
||||||
|
????
|
||||||
|
|
||||||
|
|
||||||
|
### <a name="Renum-value"></a>Enum.8: Specify enumerator values only when necessary
|
||||||
|
|
||||||
|
##### Reason
|
||||||
|
|
||||||
|
It's the simplest.
|
||||||
|
It avoids duplicate enumerator values.
|
||||||
|
The default gives a consequtive set of values that is good for `switch`-statement implementations.
|
||||||
|
|
||||||
|
##### Example
|
||||||
|
|
||||||
|
enum class Col1 { red, yellow, blue };
|
||||||
|
enum class Col2 { red=1, red=2, blue=2 }; // typo
|
||||||
|
enum class Month { jan=1, feb, mar, apr, mar, jun, jul, august, sep, oct, nov, dec }; // starting with 1 is conventional
|
||||||
|
enum class Base_flag { dec=1, oct=dec<<1, hex=dec<<2 }; // set of bits
|
||||||
|
|
||||||
|
Specifying values are neccessary to match conventional values (e.g., `Month`)
|
||||||
|
and where consecutive values are undesirable (e.g., to get separate bits as in `Base_flag`).
|
||||||
|
|
||||||
|
##### Enforcement
|
||||||
|
|
||||||
|
* Flag duplicate enumerator values
|
||||||
|
* flag explicitly specified all-consequtive enumerator values
|
||||||
|
|
||||||
|
|
||||||
# <a name="S-resource"></a>R: Resource management
|
# <a name="S-resource"></a>R: Resource management
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user