diff --git a/CppCoreGuidelines.md b/CppCoreGuidelines.md index f541835..1a672fd 100644 --- a/CppCoreGuidelines.md +++ b/CppCoreGuidelines.md @@ -1,6 +1,6 @@ # 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) -### Enum.1: Prefer enums over macros +### 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. -### Enum.2: Use enumerations to represent sets of named constants + +### 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`. + ### 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. + ### 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. -### Enum.6: Use unnamed enumerations for ??? +### 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. + + +### 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 + +???? + + +### 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 + # R: Resource management