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
july 16, 2016
July 16, 2016
Editors:
@ -7018,15 +7018,16 @@ Enumerations are used to define sets of integer values and for defining types fo
Enumeration rule summary:
* [Enum.1: Prefer enums over macros](#Renum-macro)
* [Enum.2: Use enumerations to represent sets of named constants](#Renum-set)
* [Enum.3: Prefer class enums over "plain" enums](#Renum-class)
* [Enum.1: Prefer enumerations over macros](#Renum-macro)
* [Enum.2: Use enumerations to represent sets of related named constants](#Renum-set)
* [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.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
@ -7057,23 +7058,47 @@ Instead use an `enum`:
int webby = blue; // error: be specific
Webcolor webby = Webcolor::blue;
We used an `enum class` to avoid name clashes.
##### 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
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
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
???
* 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
@ -7117,11 +7142,20 @@ Convenience of use and avoidance of errors.
##### 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
???
Flag repeated experssions cast back into a an enumeration.
### <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.
##### 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
???
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
???
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
???
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