Update CppCoreGuidelines.md

To resolve #1356, cleaned up the text for non-rules, eliminating double negatives
This commit is contained in:
Bjarne Stroustrup 2019-12-08 14:16:39 -05:00
parent f370b1fa9e
commit a58ec3ee69

View File

@ -19917,20 +19917,20 @@ The positive arguments for alternatives to these non-rules are listed in the rul
Non-rule summary:
* [NR.1: Don't: All declarations should be at the top of a function](#Rnr-top)
* [NR.2: Don't: Have only a single `return`-statement in a function](#Rnr-single-return)
* [NR.3: Don't: Don't use exceptions](#Rnr-no-exceptions)
* [NR.4: Don't: Place each class declaration in its own source file](#Rnr-lots-of-files)
* [NR.5: Don't: Don't do substantive work in a constructor; instead use two-phase initialization](#Rnr-two-phase-init)
* [NR.6: Don't: Place all cleanup actions at the end of a function and `goto exit`](#Rnr-goto-exit)
* [NR.7: Don't: Make all data members `protected`](#Rnr-protected-data)
* [NR.1: Don't insist that all declarations should be at the top of a function](#Rnr-top)
* [NR.2: Don't insist to have only a single `return`-statement in a function](#Rnr-single-return)
* [NR.3: Don't avoid exceptions](#Rnr-no-exceptions)
* [NR.4: Don't insist on placing each class declaration in its own source file](#Rnr-lots-of-files)
* [NR.5: Don't use two-phase initialization](#Rnr-two-phase-init)
* [NR.6: Don't place all cleanup actions at the end of a function and `goto exit`](#Rnr-goto-exit)
* [NR.7: Don't make all data members `protected`](#Rnr-protected-data)
* ???
### <a name="Rnr-top"></a>NR.1: Don't: All declarations should be at the top of a function
### <a name="Rnr-top"></a>NR.1: Don't insist that all declarations should be at the top of a function
##### Reason (not to follow this rule)
##### Reason
This rule is a legacy of old programming languages that didn't allow initialization of variables and constants after a statement.
Th "all declarations on top" rule is a legacy of old programming languages that didn't allow initialization of variables and constants after a statement.
This leads to longer programs and more errors caused by uninitialized and wrongly initialized variables.
##### Example, bad
@ -19964,9 +19964,9 @@ Unfortunately, compilers cannot catch all such errors and unfortunately, the bug
* [Always initialize an object](#Res-always)
* [ES.21: Don't introduce a variable (or constant) before you need to use it](#Res-introduce)
### <a name="Rnr-single-return"></a>NR.2: Don't: Have only a single `return`-statement in a function
### <a name="Rnr-single-return"></a>NR.2: Don't insist to have only a single `return`-statement in a function
##### Reason (not to follow this rule)
##### Reason
The single-return rule can lead to unnecessarily convoluted code and the introduction of extra state variables.
In particular, the single-return rule makes it harder to concentrate error checking at the top of a function.
@ -20034,15 +20034,16 @@ Also, this style is a temptation to use the [goto exit](#Rnr-goto-exit) non-rule
* Keep functions short and simple
* Feel free to use multiple `return` statements (and to throw exceptions).
### <a name="Rnr-no-exceptions"></a>NR.3: Don't: Don't use exceptions
### <a name="Rnr-no-exceptions"></a>NR.3: Don't avoid exceptions
##### Reason (not to follow this rule)
##### Reason
There seem to be three main reasons given for this non-rule:
There seem to be four main reasons given for not using exceptions:
* exceptions are inefficient
* exceptions lead to leaks and errors
* exception performance is not predictable
* the exception-handling run-time support takes up too much space
There is no way we can settle this issue to the satisfaction of everybody.
After all, the discussions about exceptions have been going on for 40+ years.
@ -20078,6 +20079,10 @@ In our opinion, you need RAII to make exception-based error handling simple and
If you are in a hard-real-time system where you must guarantee completion of a task in a given time,
you need tools to back up such guarantees.
As far as we know such tools are not available (at least not to most programmers).
* the exception-handling run-time support takes up too much space
This can be the case in small (usually embedded systesm).
However, before abandoning exceptions consider what space consistent error-handling using error-codes would require
and what failure to catch an error would cost.
Many, possibly most, problems with exceptions stem from historical needs to interact with messy old code.
@ -20103,11 +20108,11 @@ Remember
* [RAII](#Re-raii)
* Contracts/assertions: Use GSL's `Expects` and `Ensures` (until we get language support for contracts)
### <a name="Rnr-lots-of-files"></a>NR.4: Don't: Place each class declaration in its own source file
### <a name="Rnr-lots-of-files"></a>NR.4: Don't insist on placing each class declaration in its own source file
##### Reason (not to follow this rule)
##### Reason
The resulting number of files are hard to manage and can slow down compilation.
The resulting number of files from placing each class in its own file are hard to manage and can slow down compilation.
Individual classes are rarely a good logical unit of maintenance and distribution.
##### Example
@ -20118,11 +20123,11 @@ Individual classes are rarely a good logical unit of maintenance and distributio
* Use namespaces containing logically cohesive sets of classes and functions.
### <a name="Rnr-two-phase-init"></a>NR.5: Don't: Don't do substantive work in a constructor; instead use two-phase initialization
### <a name="Rnr-two-phase-init"></a>NR.5: Don't use two-phase initialization
##### Reason (not to follow this rule)
##### Reason
Following this rule leads to weaker invariants,
Splitting initialization into two rule leads to weaker invariants,
more complicated code (having to deal with semi-constructed objects),
and errors (when we didn't deal correctly with semi-constructed objects consistently).
@ -20214,9 +20219,9 @@ and errors (when we didn't deal correctly with semi-constructed objects consiste
* Always establish a class invariant in a constructor.
* Don't define an object before it is needed.
### <a name="Rnr-goto-exit"></a>NR.6: Don't: Place all cleanup actions at the end of a function and `goto exit`
### <a name="Rnr-goto-exit"></a>NR.6: Don't place all cleanup actions at the end of a function and `goto exit`
##### Reason (not to follow this rule)
##### Reason
`goto` is error-prone.
This technique is a pre-exception technique for RAII-like resource and error handling.
@ -20242,9 +20247,9 @@ and spot the bug.
* Use exceptions and [RAII](#Re-raii)
* for non-RAII resources, use [`finally`](#Re-finally).
### <a name="Rnr-protected-data"></a>NR.7: Don't: Make all data members `protected`
### <a name="Rnr-protected-data"></a>NR.7: Don't make all data members `protected`
##### Reason (not to follow this rule)
##### Reason
`protected` data is a source of errors.
`protected` data can be manipulated from an unbounded amount of code in various places.