Fix typos and add internal links.

Two hours of semi-automatic digestion of the C++ Guidelines result
in a host of small changes. Eight intermediate commits make up this
squashed monster.

First I ran 'aspell -l en_US -c CppCoreGuidelines.md' and interactively
corrected several trivial typos. Then I spent a short hour inside Vim to
improve the spacing by looking for '[a-z]  [a-z]' plus the odd typo.

Only after reading the 'how to contribute' section, I started to create
smaller patches. Continuing by reading the .md-file on formatted form, I
added a markdown link to the associated 'LICENSE' in the introduction.
Then I scanned section 'SF' and fixed typos. Next I spotted a single
problem with a French accent. After adding another internal link from
the FAQ section to the Abstract, I finished the day by reading and
correcting section CPL.
This commit is contained in:
Andreas Scherer
2015-10-14 15:52:21 +02:00
parent 9653bdb38f
commit daf2595009

View File

@@ -10,7 +10,7 @@ Editors:
This document is a very early draft. It is inkorrekt, incompleat, and pµøoorly formatted.
Had it been an open source (code) project, this would have been release 0.6.
Copying, use, modification, and creation of derivative works from this project is licensed under an MIT-style license.
Contributing to this project requires agreeing to a Contributor License. See the accompanying LICENSE file for details.
Contributing to this project requires agreeing to a Contributor License. See the accompanying [LICENSE](LICENSE) file for details.
We make this project available to "friendly users" to use, copy, modify, and derive from, hoping for constructive input.
Comments and suggestions for improvements are most welcome.
@@ -3134,7 +3134,7 @@ You need a reason (use cases) for using a hierarchy.
class Point1 {
int x, y;
// ... operations ...
// .. no virtual functions ...
// ... no virtual functions ...
};
class Point2 {
@@ -4310,7 +4310,7 @@ The common action gets tedious to write and may accidentally not be common.
##### Reason
If you need those constructors for a derived class, re-implementeing them is tedious and error prone.
If you need those constructors for a derived class, re-implementing them is tedious and error prone.
##### Example
@@ -4656,7 +4656,7 @@ The ISO standard guarantees only a "valid but unspecified" state for the standar
Here is a way to move a pointer without a test (imagine it as code in the implementation a move assignment):
// move from other.oter to this->ptr
// move from other.ptr to this->ptr
T* temp = other.ptr;
other.ptr = nullptr;
delete ptr;
@@ -5629,7 +5629,7 @@ Flag all slicing.
// ... use D's interface ...
}
else {
// .. make do with B's interface ...
// ... make do with B's interface ...
}
}
@@ -5694,7 +5694,7 @@ So, first make sure that your `dynamic_cast` really is as slow as you think it i
and that your use of `dynamic_cast` is really performance critical.
We are of the opinion that current implementations of `dynamic_cast` are unnecessarily slow.
For example, under sutitable conditions, it is possible to perform a `dynamic_cast` in [fast constant time](http://www.stroustrup.com/fast_dynamic_casting.pdf).
For example, under suitable conditions, it is possible to perform a `dynamic_cast` in [fast constant time](http://www.stroustrup.com/fast_dynamic_casting.pdf).
However, compatibility makes changes difficult even if all agree that an effort to optimize is worth while.
##### Enforcement
@@ -6399,14 +6399,14 @@ We can fix that problem by making ownership explicit:
##### Note
The fact that there are billions of lines of code that violates this rule against owning `T*`s cannot be ignored.
The fact that there are billions of lines of code that violate this rule against owning `T*`s cannot be ignored.
This code cannot all be rewritten (ever assuming good code transformation software).
This problem cannot be solved (at scale) by transforming all owning pointer to `unique_ptr`s and `shared_ptr`s, partly because we need/use owning "raw pointers" in the implementation of our fundamental resource handles. For example, most `vector` implementations have one owning pointer and two non-owning pointers.
Also, many ABIs (and essentially all interfaces to C code) use `T*`s, some of them owning.
##### Note
`owner<T>` has no default semantics beyond `T*` it can be used without changing any code using it and without affecting ABIs.
`owner<T>` has no default semantics beyond `T*`. It can be used without changing any code using it and without affecting ABIs.
It is simply a (most valuable) indicator to programmers and analysis tools.
For example, if an `owner<T>` is a member of a class, that class better have a destructor that `delete`s it.
@@ -6428,7 +6428,7 @@ Returning a (raw) pointer imposes a life-time management burden on the caller; t
delete p;
}
In addition to suffering from then problem from [leak](#???), this adds a spurious allocation and deallocation operation, and is needlessly verbose. If Gadget is cheap to move out of a function (i.e., is small or has an efficient move operation), just return it "by value:'
In addition to suffering from the problem from [leak](#???), this adds a spurious allocation and deallocation operation, and is needlessly verbose. If Gadget is cheap to move out of a function (i.e., is small or has an efficient move operation), just return it "by value:'
Gadget make_gadget(int n)
{
@@ -6443,7 +6443,7 @@ This rule applies to factory functions.
##### Note
If pointer semantics is required (e.g., because the return type needs to refer to a base class of a class hierarchy (an interface)), return a "smart pointer."
If pointer semantics are required (e.g., because the return type needs to refer to a base class of a class hierarchy (an interface)), return a "smart pointer."
##### Enforcement
@@ -6480,12 +6480,12 @@ See [the raw pointer rule](#Rr-ptr)
##### Reason
A scoped object is a local object, a global object, or a member.
This implies that there is no separate allocation and deallocation cost in excess that already used for the containing scope or object.
This implies that there is no separate allocation and deallocation cost in excess of that already used for the containing scope or object.
The members of a scoped object are themselves scoped and the scoped object's constructor and destructor manage the members' lifetimes.
##### Example
the following example is inefficient (because it has unnecessary allocation and deallocation), vulnerable to exception throws and returns in the "¦ part (leading to leaks), and verbose:
The following example is inefficient (because it has unnecessary allocation and deallocation), vulnerable to exception throws and returns in the "¦ part (leading to leaks), and verbose:
void some_function(int n)
{
@@ -6516,13 +6516,13 @@ They are a notable source of errors.
**Warning**: The initialization of global objects is not totally ordered. If you use a global object initialize it with a constant.
**Exception**: a global object is often better than a singleton.
**Exception**: A global object is often better than a singleton.
**Exception**: An immutable (`const`) global does not introduce the problems we try to avoid by banning global objects.
##### Enforcement
(??? NM: Obviously we can warn about non-`const` statics....do we want to?)
(??? NM: Obviously we can warn about non-`const` statics ... do we want to?)
## <a name="SS-alloc"></a> R.alloc: Allocation and deallocation
@@ -6563,9 +6563,9 @@ In some implementations that `delete` and that `free()` might work, or maybe the
##### Exception
There are applications and sections of code where exceptions are not acceptable.
Some of the best such example are in life-critical hard real-time code.
Some of the best such examples are in life-critical hard real-time code.
Beware that many bans on exception use are based on superstition (bad)
or by concerns for older code bases with unsystematics resource management (unfortunately, but sometimes necessary).
or by concerns for older code bases with unsystematic resource management (unfortunately, but sometimes necessary).
In such cases, consider the `nothrow` versions of `new`.
##### Enforcement
@@ -6577,7 +6577,7 @@ Flag explicit use of `malloc` and `free`.
##### Reason
The pointer returned by `new` should belong to a resource handle (that can call `delete`).
If the pointer returned from `new` is assigned to a plain/naked pointer, the object can be leaked.
If the pointer returned by `new` is assigned to a plain/naked pointer, the object can be leaked.
##### Note
@@ -7234,7 +7234,7 @@ Readability. Minimize resource retention. Avoid accidental misuse of value.
This function is by most measure too long anyway, but the point is that the used by `fn` and the file handle held by `is`
are retained for much longer than needed and that unanticipated use of `is` and `fn` could happen later in the function.
In this case, it might be a good ide to factor out the read:
In this case, it might be a good idea to factor out the read:
void fill_record(Record& r, const string& name)
{
@@ -7272,7 +7272,7 @@ Readability. Minimize resource retention.
v.push_back(s);
for (int i = 0; i < 20; ++i) { // good: i is local to for-loop
//* ...
// ...
}
if (auto pc = dynamic_cast<Circle*>(ps)) { // good: pc is local to if-statement
@@ -7618,7 +7618,7 @@ A good optimizer should know about input operations and eliminate the redundant
##### Example
Using an `unitialized` value is a symptom of a problem and not a solution:
Using an `uninitialized` value is a symptom of a problem and not a solution:
widget i = uninit; // bad
widget j = uninit;
@@ -7636,7 +7636,7 @@ Using an `unitialized` value is a symptom of a problem and not a solution:
j = f4();
}
Now the compiler cannot even simply detect a used-befor-set.
Now the compiler cannot even simply detect a used-before-set.
##### Note
@@ -8664,7 +8664,7 @@ It makes a lie out of `const`.
##### Note
Usually the reason to "cast away `const`" is to allow the updating of some transient information of an otherwise immutable object.
Examples are cashing, mnemorization, and precomputation.
Examples are cashing, memorization, and precomputation.
Such examples are often handled as well or better using `mutable` or an indirection than with a `const_cast`.
##### Example
@@ -9133,7 +9133,7 @@ Concurrency rule summary:
Speaking of concurrency, should there be a note about the dangers of `std::atomic` (weapons)?
A lot of people, myself included, like to experiment with `std::memory_order`, but it is perhaps best to keep a close watch on those things in production code.
Even vendors mess this up: Microsoft had to fix their `shared_ptr` (weak refcount decrement wasn't synchronized-with the destructor, if I recall correctly, although it was only a problem on ARM, not Intel)
and everyone (gcc, clang, Microsoft, and intel) had to fix their `compare_exchange_*` this year, after an implementation bug caused losses to some finance company and they were kind enough to let the community know.
and everyone (gcc, clang, Microsoft, and Intel) had to fix their `compare_exchange_*` this year, after an implementation bug caused losses to some finance company and they were kind enough to let the community know.
It should definitely be mentioned that `volatile` does not provide atomicity, does not synchronize between threads, and does not prevent instruction reordering (neither compiler nor hardware), and simply has nothing to do with concurrency.
@@ -11000,7 +11000,7 @@ Assume that `Apple` and `Pear` are two kinds of `Fruit`s.
Apple& a0 = &aa[0]; // a Pear?
Apple& a1 = &aa[1]; // a Pear?
Probably, `aa[0]` will be a `Pear` (without the use af a cast!).
Probably, `aa[0]` will be a `Pear` (without the use of a cast!).
If `sizeof(Apple) != sizeof(Pear)` the access to `aa[1]` will not be aligned to the proper start of an object in the array.
We have a type violation and possibly (probably) a memory corruption.
Never write such code.
@@ -11505,7 +11505,7 @@ That subset can be compiled with both C and C++ compilers, and when compiled as
##### Reason
C++ is more expressive than C and offer better support for many types of programming.
C++ is more expressive than C and offers better support for many types of programming.
##### Example
@@ -11543,7 +11543,7 @@ None needed
# <a name="S-source"></a> SF: Source files
Distinguish between declarations (used as interfaces) and definitions (used as implementations)
Distinguish between declarations (used as interfaces) and definitions (used as implementations).
Use header files to represent interfaces and to emphasize logical structure.
Source file rule summary:
@@ -11825,8 +11825,8 @@ It is almost always a bug to mention an unnamed namespace in a header file.
##### Reason
nothing external can depend on an entity in a nested unnamed namespace.
Consider putting every definition in an implementation source file should be in an unnamed namespace unless that is defining an "external/exported" entity.
Nothing external can depend on an entity in a nested unnamed namespace.
Consider putting every definition in an implementation source file in an unnamed namespace unless that is defining an "external/exported" entity.
##### Example
@@ -11933,9 +11933,9 @@ Many
* see "stopping programmers from doing unusual things" as their primary aim
* aim at portability across many compilers (some 10 years old)
* are written to preserve decades old code bases
* aims at a single application domain
* aim at a single application domain
* are downright counterproductive
* are ignored (must be ignored for programmers to get their work done well)
* are ignored (must be ignored by programmers to get their work done well)
A bad coding standard is worse than no coding standard.
However an appropriate set of guidelines are much better than no standards: "Form is liberating."
@@ -11983,7 +11983,7 @@ Reference sections:
Any similarities to this set of guidelines are unsurprising because Bjarne Stroustrup was an author of JSF++.
Recommended, but note its very specific focus.
* [Mozilla Portability Guide](https://developer.mozilla.org/en-US/docs/Mozilla/C%2B%2B_Portability_Guide).
As the name indicate, this aims for portability across many (old) compilers.
As the name indicates, this aims for portability across many (old) compilers.
As such, it is restrictive.
* [Geosoft.no: C++ Programming Style Guidelines](http://geosoft.no/development/cppstyle.html).
???.
@@ -12025,8 +12025,7 @@ Reference sections:
* [isocpp.org](http://www.isocpp.com)
* [Bjarne Stroustrup's home pages](http://www.stroustrup.com)
* [WG21](http://www.open-std.org/jtc1/sc22/wg21/)
* <a name="Boost"></a>
[Boost](http://www.boost.org)
* [Boost](http://www.boost.org)<a name="Boost"></a>
* [Adobe open source](http://www.adobe.com/open-source.html)
* [Poco libraries](http://pocoproject.org/)
@@ -12927,7 +12926,7 @@ Too much space makes the text larger and distracts.
##### Note
Some IDEs have their own opinions and adds distracting space.
Some IDEs have their own opinions and add distracting space.
##### Note
@@ -13071,7 +13070,7 @@ This section covers answers to frequently asked questions about these guidelines
### <a name="Faq-aims"></a> FAQ.1: What do these guidelines aim to achieve?
See the top of this page. This is an open source project to maintain modern authoritative guidelines for writing C++ code using the current C++ Standard (as of this writing, C++14). The guidelines are designed to be modern, machine-enforceable wherever possible, and open to contributions and forking so that organizations can easily incorporate them into their own corporate coding guidelines.
See the <a href="#S-abstract">top of this page</a>. This is an open source project to maintain modern authoritative guidelines for writing C++ code using the current C++ Standard (as of this writing, C++14). The guidelines are designed to be modern, machine-enforceable wherever possible, and open to contributions and forking so that organizations can easily incorporate them into their own corporate coding guidelines.
### <a name="Faq-announced"></a> FAQ.2: When and where was this work first announced?
@@ -13770,7 +13769,7 @@ A relatively informal definition of terms used in the guidelines
Thus, to produce acceptable code, we sometimes have to do more than just follow the formal specification.
* *cost*:the expense (e.g., in programmer time, run time, or space) of producing a program or of executing it.
Ideally, cost should be a function of complexity.
* *customisation point*: ???
* *customization point*: ???
* *data*:values used in a computation.
* *debugging*:the act of searching for and removing errors from a program; usually far less systematic than testing.
* *declaration*:the specification of a name with its type in a program.
@@ -13882,11 +13881,11 @@ Alternatively, we will decide that no change is needed and delete the entry.
* Should physical design (what's in a file) and large-scale design (libraries, groups of libraries) be addressed?
* Namespaces
* How granular should namespaces be? All classes/functions designed to work together and released together (as defined in Sutter/Alexandrescu) or something narrower or wider?
* Should there be inline namespaces (a-la `std::literals::*_literals`)?
* Should there be inline namespaces (à la `std::literals::*_literals`)?
* Avoid implicit conversions
* Const member functions should be thread safe "¦ aka, but I don't really change the variable, just assign it a value the first time its called "¦ argh
* Always initialize variables, use initialization lists for member variables.
* Anyone writing a public interface which takes or returns void* should have their toes set on fire. That one has been a personal favourite of mine for a number of years. :)
* Anyone writing a public interface which takes or returns void* should have their toes set on fire. That one has been a personal favorite of mine for a number of years. :)
* Use `const`'ness wherever possible: member functions, variables and (yippee) `const_iterators`
* Use `auto`
* `(size)` vs. `{initializers}` vs. `{Extent{size}}`