Skip to content

Commit 4a738aa

Browse files
committed
Merge pull request #1 from isocpp/master
Sync the fork
2 parents a67f8d3 + ad97ba3 commit 4a738aa

File tree

1 file changed

+121
-32
lines changed

1 file changed

+121
-32
lines changed

CppCoreGuidelines.md

Lines changed: 121 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2641,7 +2641,7 @@ A `span` represents a range of elements, but how do we manipulate elements of th
26412641
for (int x : s) cout << x << '\n'; // range traversal (guaranteed correct)
26422642
for (int i = 0; i<s.size(); ++i) cout << x << '\n'; // C-style traversal (potentially checked)
26432643
s[7] = 9; // random access (potentially checked)
2644-
std::sort(&s[0],&s[s.size()/2); // extract pointers (potentially checked)
2644+
std::sort(&s[0],&s[s.size()/2]); // extract pointers (potentially checked)
26452645
}
26462646

26472647
##### Note
@@ -3216,6 +3216,8 @@ Class rule summary:
32163216
* [C.4: Make a function a member only if it needs direct access to the representation of a class](#Rc-member)
32173217
* [C.5: Place helper functions in the same namespace as the class they support](#Rc-helper)
32183218
* [C.7: Don't define a class or enum and declare a variable of its type in the same statement](#Rc-standalone)
3219+
* [C.8: use `class` rather that `struct` if any member is non-public](#Rc-class)
3220+
* [C.9: minimize exposure of members](#Rc-private)
32193221

32203222
Subsections:
32213223

@@ -3254,11 +3256,18 @@ Probably impossible. Maybe a heuristic looking for data items used together is p
32543256

32553257
##### Reason
32563258

3257-
Ease of comprehension. The use of `class` alerts the programmer to the need for an invariant.
3259+
Readability.
3260+
Ease of comprehension.
3261+
The use of `class` alerts the programmer to the need for an invariant.
3262+
This is a useful convention.
32583263

32593264
##### Note
32603265

3261-
An invariant is a logical condition for the members of an object that a constructor must establish for the public member functions to assume. After the invariant is established (typically by a constructor) every member function can be called for the object. An invariant can be stated informally (e.g., in a comment) or more formally using `Expects`.
3266+
An invariant is a logical condition for the members of an object that a constructor must establish for the public member functions to assume.
3267+
After the invariant is established (typically by a constructor) every member function can be called for the object.
3268+
An invariant can be stated informally (e.g., in a comment) or more formally using `Expects`.
3269+
3270+
If all data members can vary independently of each other, no invariant is possible.
32623271

32633272
##### Example
32643273

@@ -3270,14 +3279,25 @@ An invariant is a logical condition for the members of an object that a construc
32703279
but:
32713280

32723281
class Date {
3282+
public:
3283+
Date(int yy, Month mm, char dd); // validate that {yy, mm, dd} is a valid date and initialize
3284+
// ...
32733285
private:
32743286
int y;
32753287
Month m;
32763288
char d; // day
3277-
public:
3278-
Date(int yy, Month mm, char dd); // validate that {yy, mm, dd} is a valid date and initialize
3279-
// ...
32803289
};
3290+
3291+
##### Note
3292+
3293+
If a class has any `private` data, a user cannot completely initialize an object without the use of a constructor.
3294+
Hence, the class definer will provide a constructor and must specify its meaning.
3295+
This effectivily means the definer need to define an invariant.
3296+
3297+
* See also [define a class with private data as `class`](#Rc-class).
3298+
* See also [Prefer to place the interface first in a class](#Rl-order).
3299+
* See also [minimize exposure of members](#Rc-private).
3300+
* See also [Avoid `protected` data](#Rh-protected).
32813301

32823302
##### Enforcement
32833303

@@ -3387,6 +3407,63 @@ Mixing a type definition and the definition of another entity in the same declar
33873407
* Flag if the `}` of a class or enumeration definition is not followed by a `;`. The `;` is missing.
33883408

33893409

3410+
### <a name="Rc-class"></a>C.8: use `class` rather that `struct` if any member is non-public
3411+
3412+
##### Reason
3413+
3414+
Readability.
3415+
To make it clear that something is being hidden/abstracted.
3416+
This is a useful convention.
3417+
3418+
##### Example, bad
3419+
3420+
struct Date {
3421+
int d,m;
3422+
3423+
Date(int i, Month m);
3424+
// ... lots of functions ...
3425+
private:
3426+
int y; // year
3427+
};
3428+
3429+
There is nothing wrong with this code as far as the C++ language rules are concerned,
3430+
but nearly everything is wrong from a design perspective.
3431+
The private data is hidden far from the public data.
3432+
The data is split in different parts of the class declaration.
3433+
Different parts of the data has difference access.
3434+
All of this decreases readability and complicates maintenance.
3435+
3436+
3437+
##### Note
3438+
3439+
Prefer to place the interface first in a class [see](#Rl-order).
3440+
3441+
##### Enforcement
3442+
3443+
Flag classes declarate with `struct` if there is a `private` or `public` member.
3444+
3445+
3446+
### <a name="Rc-private"></a>C.9: minimize exposure of members
3447+
3448+
##### Reason
3449+
3450+
Encapsulation.
3451+
Information hiding.
3452+
Mimimize the chance of untended access.
3453+
This simplifies maintenance.
3454+
3455+
##### Example
3456+
3457+
???
3458+
3459+
##### Note
3460+
3461+
Prefer the order `public` members before `protected` members before `private` members [see](#Rl-order).
3462+
3463+
##### Enforcement
3464+
3465+
???
3466+
33903467
## <a name="SS-concrete"></a>C.concrete: Concrete types
33913468

33923469
One ideal for a class is to be a regular type.
@@ -5495,7 +5572,6 @@ Designing rules for classes in a hierarchy summary:
54955572
* [C.128: Use `override` to make overriding explicit in large class hierarchies](#Rh-override)
54965573
* [C.129: When designing a class hierarchy, distinguish between implementation inheritance and interface inheritance](#Rh-kind)
54975574
* [C.130: Redefine or prohibit copying for a base class; prefer a virtual `clone` function instead](#Rh-copy)
5498-
54995575
* [C.131: Avoid trivial getters and setters](#Rh-get)
55005576
* [C.132: Don't make a function `virtual` without reason](#Rh-virtual)
55015577
* [C.133: Avoid `protected` data](#Rh-protected)
@@ -8102,9 +8178,10 @@ The *always initialize* rule is a style rule aimed to improve maintainability as
81028178

81038179
Here is an example that is often considered to demonstrate the need for a more relaxed rule for initialization
81048180

8105-
widget i, j; // "widget" a type that's expensive to initialize, possibly a large POD
8181+
widget i; // "widget" a type that's expensive to initialize, possibly a large POD
8182+
widget j;
81068183

8107-
if (cond) { // bad: i and j are initialized "late"
8184+
if (cond) { // bad: i and j are initialized "late"
81088185
i = f1();
81098186
j = f2();
81108187
}
@@ -8939,7 +9016,7 @@ Readability.
89399016

89409017
##### Enforcement
89419018

8942-
Flag empty statements that are not blocks and doesn't "contain" comments.
9019+
Flag empty statements that are not blocks and don't "contain" comments.
89439020

89449021

89459022
### <a name="Res-loop-counter"></a>ES.86: Avoid modifying loop control variables inside the body of raw for-loops
@@ -9301,7 +9378,7 @@ Flag `const_cast`s.
93019378

93029379
##### Reason
93039380

9304-
Constructs that cannot overflow, don't, and usually runs faster:
9381+
Constructs that cannot overflow, don't, and usually run faster:
93059382

93069383
##### Example
93079384

@@ -9383,7 +9460,7 @@ also define an overload that takes lvalues.
93839460
void print(const string& s); // print and preserve the value of s
93849461

93859462
An rvalue can be assumed not to be accessed after being passed.
9386-
An lvalue must in general be assumed to be used again after being passes, that is after a `std::move`,
9463+
An lvalue must in general be assumed to be used again after being passed, that is after a `std::move`,
93879464
so "careful programming" is essential to avoid disasters -- better not rely on that.
93889465

93899466
###### Note
@@ -9861,7 +9938,7 @@ See also:
98619938

98629939
It is hard to be certain that concurrency isn't used now or sometime in the future.
98639940
Code gets re-used.
9864-
Libraries using threads my be used from some other part of the program.
9941+
Libraries using threads may be used from some other part of the program.
98659942
Note that this applies most urgently to library code and least urgently to stand-alone applications.
98669943

98679944
##### Example
@@ -9894,7 +9971,7 @@ There are several ways that this example could be made safe for a multi-threaded
98949971
However, there are also many examples where code that was "known" to never run in a multi-threaded program
98959972
was run as part of a multi-threaded program. Often years later.
98969973
Typically, such programs lead to a painful effort to remove data races.
9897-
Therefore, code that is never intended to run in a multi-threaded environment should be clearly labeled as such.
9974+
Therefore, code that is never intended to run in a multi-threaded environment should be clearly labeled as such and ideally come with compile or run-time enforcement mechanisms to catch those usage bugs early.
98989975

98999976
### <a name="Rconc-races"></a>CP.2: Avoid data races
99009977

@@ -9980,7 +10057,7 @@ Error handling involves:
998010057
* Preserve the state of a program in a valid state
998110058
* Avoid resource leaks
998210059

9983-
It is not possible to recover from all errors. If recovery from an error is not possible, it is important to quickly "get out" in a well-defined way. A strategy for error handling must be simple, or it becomes a source of even worse errors.
10060+
It is not possible to recover from all errors. If recovery from an error is not possible, it is important to quickly "get out" in a well-defined way. A strategy for error handling must be simple, or it becomes a source of even worse errors. Untested and rarely executed error-handling code is itself the source of many bugs.
998410061

998510062
The rules are designed to help avoid several kinds of errors:
998610063

@@ -10106,7 +10183,7 @@ There is nothing exceptional about finding a value in a `vector`.
1010610183

1010710184
##### Reason
1010810185

10109-
To use an objects it must be in a valid state (defined formally or informally by an invariant) and to recover from an error every object not destroyed must be in a valid state.
10186+
To use an object it must be in a valid state (defined formally or informally by an invariant) and to recover from an error every object not destroyed must be in a valid state.
1011010187

1011110188
##### Note
1011210189

@@ -10117,7 +10194,7 @@ An [invariant](#Rc-struct) is logical condition for the members of an object tha
1011710194
##### Reason
1011810195

1011910196
Leaving an object without its invariant established is asking for trouble.
10120-
Not all member function can be called.
10197+
Not all member functions can be called.
1012110198

1012210199
##### Example
1012310200

@@ -10162,7 +10239,7 @@ This is verbose. In larger code with multiple possible `throw`s explicit release
1016210239

1016310240
void f3(int i) // OK: resource management done by a handle
1016410241
{
10165-
auto p = make_unique<int[12]>();
10242+
auto p = make_unique<int[]>(12);
1016610243
// ...
1016710244
if (i < 17) throw Bad {"in f()", i};
1016810245
// ...
@@ -10172,7 +10249,7 @@ Note that this works even when the `throw` is implicit because it happened in a
1017210249

1017310250
void f4(int i) // OK: resource management done by a handle
1017410251
{
10175-
auto p = make_unique<int[12]>();
10252+
auto p = make_unique<int[]>(12);
1017610253
// ...
1017710254
helper(i); // may throw
1017810255
// ...
@@ -10199,12 +10276,12 @@ First challenge that assumption; there are many anti-exceptions myths around.
1019910276
We know of only a few good reasons:
1020010277

1020110278
* We are on a system so small that the exception support would eat up most of our 2K or memory.
10202-
* We are in a hard-real-time system and we don't have tools that allows us that an exception is handled within the required time.
10279+
* We are in a hard-real-time system and we don't have tools that guarantee us that an exception is handled within the required time.
1020310280
* We are in a system with tons of legacy code using lots of pointers in difficult-to-understand ways
1020410281
(in particular without a recognizable ownership strategy) so that exceptions could cause leaks.
1020510282
* We get fired if we challenge our manager's ancient wisdom.
1020610283

10207-
Only the first of these reasons is fundamental, so whenever possible, use exception to implement RAII.
10284+
Only the first of these reasons is fundamental, so whenever possible, use exceptions to implement RAII, or design your RAII objects to never fail.
1020810285
When exceptions cannot be used, simulate RAII.
1020910286
That is, systematically check that objects are valid after construction and still release all resources in the destructor.
1021010287
One strategy is to add a `valid()` operation to every resource handle:
@@ -10276,7 +10353,7 @@ Many standard library functions are `noexcept` including all the standard librar
1027610353
// ... do something ...
1027710354
}
1027810355

10279-
The `noexcept` here states that I am not willing or able to handle the situation where I cannot construct the local `vector`. That is, I consider memory exhaustion a serious design error (on line with hardware failures) so that I'm willing to crash the program if it happens.
10356+
The `noexcept` here states that I am not willing or able to handle the situation where I cannot construct the local `vector`. That is, I consider memory exhaustion a serious design error (on par with hardware failures) so that I'm willing to crash the program if it happens.
1028010357

1028110358
**See also**: [discussion](#Sd-noexcept).
1028210359

@@ -10409,7 +10486,7 @@ Instead, use:
1040910486

1041010487
##### Enforcement
1041110488

10412-
Flag by-value exceptions if their type are part of a hierarchy (could require whole-program analysis to be perfect).
10489+
Flag by-value exceptions if their types are part of a hierarchy (could require whole-program analysis to be perfect).
1041310490

1041410491
### <a name="Re-never-fail"></a>E.16: Destructors, deallocation, and `swap` must never fail
1041510492

@@ -10431,15 +10508,15 @@ We don't know how to write reliable programs if a destructor, a swap, or a memor
1043110508

1043210509
##### Note
1043310510

10434-
Many have tried to write reliable code violating this rule for examples such as a network connection that "refuses to close". To the best of our knowledge nobody has found a general way of doing this though occasionally, for very specific examples, you can get away with setting some state for future cleanup. Every example, we have seen of this is error-prone, specialized, and usually buggy.
10511+
Many have tried to write reliable code violating this rule for examples such as a network connection that "refuses to close". To the best of our knowledge nobody has found a general way of doing this though occasionally, for very specific examples, you can get away with setting some state for future cleanup. Every example we have seen of this is error-prone, specialized, and usually buggy.
1043510512

1043610513
##### Note
1043710514

1043810515
The standard library assumes that destructors, deallocation functions (e.g., `operator delete`), and `swap` do not throw. If they do, basic standard library invariants are broken.
1043910516

1044010517
##### Note
1044110518

10442-
Deallocation functions, including `operator delete`, must be `noexcept`. `swap` functions must be `noexcept`. Most destructors are implicitly `noexcept` by default. destructors, make them `noexcept`.
10519+
Deallocation functions, including `operator delete`, must be `noexcept`. `swap` functions must be `noexcept`. Most destructors are implicitly `noexcept` by default.
1044310520

1044410521
##### Enforcement
1044510522

@@ -10513,7 +10590,7 @@ Let cleanup actions on the unwinding path be handled by [RAII](#Re-raii).
1051310590
# <a name="S-const"></a>Con: Constants and Immutability
1051410591

1051510592
You can't have a race condition on a constant.
10516-
it is easier to reason about a program when many of the objects cannot change their values.
10593+
It is easier to reason about a program when many of the objects cannot change their values.
1051710594
Interfaces that promises "no change" of objects passed as arguments greatly increase readability.
1051810595

1051910596
Constant rule summary:
@@ -10607,6 +10684,10 @@ This gives a more precise statement of design intent, better readability, more e
1060710684

1060810685
???
1060910686

10687+
##### Note
10688+
10689+
See F.4.
10690+
1061010691
##### Enforcement
1061110692

1061210693
???
@@ -10994,7 +11075,7 @@ It is better and simpler just to use `Sortable`:
1099411075

1099511076
##### Note
1099611077

10997-
The set of "standard" concepts is evolving as we approaches real (ISO) standardization.
11078+
The set of "standard" concepts is evolving as we approach real (ISO) standardization.
1099811079

1099911080
##### Note
1100011081

@@ -11145,7 +11226,7 @@ Examples of complete sets are
1114511226
##### Reason
1114611227

1114711228
A meaningful/useful concept has a semantic meaning.
11148-
Expressing this semantics in a informal, semi-formal, or formal way makes the concept comprehensible to readers and the effort to express it can catch conceptual errors.
11229+
Expressing these semantics in an informal, semi-formal, or formal way makes the concept comprehensible to readers and the effort to express it can catch conceptual errors.
1114911230
Specifying semantics is a powerful design tool.
1115011231

1115111232
##### Example
@@ -11310,7 +11391,7 @@ Conversions are taken into account. You don't have to remember the names of all
1131011391
##### Reason
1131111392

1131211393
Function objects can carry more information through an interface than a "plain" pointer to function.
11313-
In general, passing function objects give better performance than passing pointers to functions.
11394+
In general, passing function objects gives better performance than passing pointers to functions.
1131411395

1131511396
##### Example
1131611397

@@ -11381,7 +11462,7 @@ This saves the user of `Matrix` from having to know that its elements are stored
1138111462
##### Example
1138211463

1138311464
template<typename T>
11384-
using Value_type<T> = container_traits<T>::value_type;
11465+
using Value_type = typename container_traits<T>::value_type;
1138511466

1138611467
This saves the user of `Value_type` from having to know the technique used to implement `value_type`s.
1138711468

@@ -11742,7 +11823,7 @@ There are three major ways to let calling code customize a template.
1174211823

1174311824
Templates are the backbone of C++'s support for generic programming and class hierarchies the backbone of its support
1174411825
for object-oriented programming.
11745-
The two language mechanisms can be use effectively in combination, but a few design pitfalls must be avoided.
11826+
The two language mechanisms can be used effectively in combination, but a few design pitfalls must be avoided.
1174611827

1174711828
### <a name="Rt-hier"></a>T.80: Do not naively templatize a class hierarchy
1174811829

@@ -12162,7 +12243,8 @@ That makes the code concise and gives better locality than alternatives.
1216212243

1216312244
##### Example
1216412245

12165-
??? for-loop equivalent
12246+
auto earlyUsersEnd = std::remove_if(users.begin(), users.end(),
12247+
[](const User &a) { return a.id > 100; });
1216612248

1216712249
**Exception**: Naming a lambda can be useful for clarity even if it is used only once
1216812250

@@ -13886,10 +13968,17 @@ Use the `public` before `protected` before `private` order.
1388613968

1388713969
Private types and functions can be placed with private data.
1388813970

13971+
Avoid multiple blocks of declarations of one access (e.g., `public`) dispersed among blocks of declarations with different access (e.g. `private`).
13972+
1388913973
##### Example
1389013974

1389113975
???
1389213976

13977+
##### Note
13978+
13979+
The use of macros to declare groups of members often violates any ordering rules.
13980+
However, macros obscures what is being expressed anyway.
13981+
1389313982
##### Enforcement
1389413983

1389513984
Flag departures from the suggested order. There will be a lot of old code that doesn't follow this rule.

0 commit comments

Comments
 (0)