mirror of
https://github.com/isocpp/CppCoreGuidelines.git
synced 2024-03-22 13:30:58 +08:00
Update and extension of enumeration section
This commit is contained in:
parent
39eaac7317
commit
ae8c320cdf
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user