Update and extension of enumeration section

This commit is contained in:
Bjarne Stroustrup
2016-07-16 18:13:43 -04:00
parent 39eaac7317
commit ae8c320cdf

View File

@@ -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