mirror of
https://github.com/isocpp/CppCoreGuidelines.git
synced 2024-03-22 13:30:58 +08:00
Merge branch 'flippingtables-master'
This commit is contained in:
commit
a672faaad8
|
@ -842,7 +842,7 @@ Alternatively, mark an owner as such using `owner` from [the GSL](#S-support).
|
|||
// ...
|
||||
}
|
||||
|
||||
Yes, this is a carricature, but we have seen every individual mistake in production code, and worse.
|
||||
Yes, this is a caricature, but we have seen every individual mistake in production code, and worse.
|
||||
Note that the layout of `X` guarantees that at least 6 bytes (and most likely more) bytes are wasted.
|
||||
The spurious definition of copy operations disables move semantics so that the return operation is slow.
|
||||
The use of `new` and `delete` for `buf` is redundant; if we really needed a local string, we should use a local `string`.
|
||||
|
@ -996,7 +996,7 @@ That's part of the problem.
|
|||
|
||||
This one of the most effective solution to problem related to initialization order.
|
||||
In a multi-threaded environment the initialization of the static object does not introduce a race condition
|
||||
(unless you carelessly access a shared objects from within its consructor).
|
||||
(unless you carelessly access a shared objects from within its constructor).
|
||||
|
||||
If you, as many do, define a singleton as a class for which only one object is created, functions like `myX` are not singletons,
|
||||
and this useful technique is not an exception to the no-singleton rule.
|
||||
|
@ -1514,7 +1514,7 @@ This will force every derived class to compute a center -- even if that's non-tr
|
|||
|
||||
**Exception**: You can carefully craft an interface using a few carefully selected higher-level C++ types. See ???.
|
||||
|
||||
**Exception**: Common ABIs are emerging on some platfoms freeing you from the more Draconian restrictions.
|
||||
**Exception**: Common ABIs are emerging on some platforms freeing you from the more Draconian restrictions.
|
||||
|
||||
**Note**: if you use a single compiler, you can use full C++ in interfaces. That may require recompilation after an upgrade to a new compiler version.
|
||||
|
||||
|
@ -1603,7 +1603,7 @@ If something is a well-specified action, separate it out from its surrounding c
|
|||
Almost everything is wrong with `read_and_print`.
|
||||
It reads, it writes (to a fixed `ostream`), it write error messages (to a fixed `ostream`), it handles only `int`s.
|
||||
There is nothing to reuse, logically separate operations are intermingled and local variables are in scope after the end of their logical use.
|
||||
For a tiny example, this looks OK, but if the input opeartion, the output operation, and the error handling had been more complicated the tangled
|
||||
For a tiny example, this looks OK, but if the input operation, the output operation, and the error handling had been more complicated the tangled
|
||||
mess could become hard to understand.
|
||||
|
||||
**Note**: If you write a non-trivial lambda that potentially can be used in more than one place,
|
||||
|
@ -1695,7 +1695,7 @@ If there was a need, we could further templatize `read()` and `print()` on the d
|
|||
### F.3: Keep functions short and simple
|
||||
|
||||
**Reason**: Large functions are hard to read, more likely to contain complex code, and more likely to have variables in larger than minimal scopes.
|
||||
Functions with complex control stryuctures are more likely to be long and more likely to hide logical errors
|
||||
Functions with complex control structures are more likely to be long and more likely to hide logical errors
|
||||
|
||||
**Example**: Consider
|
||||
|
||||
|
@ -1809,7 +1809,7 @@ This is usually a very good thing.
|
|||
|
||||
**Note**: Don't try to make all functions `constexpr`. Most computation is best done at run time.
|
||||
|
||||
**Enforcement**: Imposible and unnecessary.
|
||||
**Enforcement**: Impossible and unnecessary.
|
||||
The compiler gives an error if a non-`constexpr` function is called where a constant is required.
|
||||
|
||||
|
||||
|
@ -2389,12 +2389,12 @@ This applies to references as well:
|
|||
{
|
||||
int x = 7;
|
||||
// ...
|
||||
return x; // Bad: returns refence to object that is about to be destroyed
|
||||
return x; // Bad: returns reference to object that is about to be destroyed
|
||||
}
|
||||
|
||||
**See also**: [discussion of dangling pointer prevention](#???).
|
||||
|
||||
**Enforcement**: A slightly diffent variant of the problem is placing pointers in a container that outlives the objects pointed to.
|
||||
**Enforcement**: A slightly different variant of the problem is placing pointers in a container that outlives the objects pointed to.
|
||||
|
||||
* Compilers tend to catch return of reference to locals and could in many cases catch return of pointers to locals.
|
||||
* Static analysis can catch most (all?) common patterns of the use of pointers indicating positions (thus eliminating dangling pointers)
|
||||
|
@ -2716,7 +2716,7 @@ but
|
|||
For example, we can now change the representation of a `Date` without affecting its users (recompilation is likely, though).
|
||||
|
||||
**Note**: Using a class in this way to represent the distinction between interface and implementation is of course not the only way.
|
||||
For example, we can use a set of declarations of freestandanding functions in a namespace,
|
||||
For example, we can use a set of declarations of freestanding functions in a namespace,
|
||||
an abstract base class,
|
||||
or a template fuction with concepts to represent an interface.
|
||||
The most important issue is to explicitly distinguish between an interface and its implementation "details."
|
||||
|
@ -2837,7 +2837,7 @@ You need a reason (use cases) for using a hierarchy.
|
|||
}
|
||||
|
||||
If a class can be part of a hierarchy, we (in real code if not necessarily in small examples) must manipulate its objects through pointers or references.
|
||||
That implies more memory overhead, more allocations and deallocations, and more run-time overhead to perform the resulting indiretions.
|
||||
That implies more memory overhead, more allocations and deallocations, and more run-time overhead to perform the resulting indirections.
|
||||
|
||||
**Note**: Concrete types can be stack allocated and be members of other classes.
|
||||
|
||||
|
@ -3297,7 +3297,7 @@ Assigning a `Triangle` to a `Circle`?
|
|||
Unless `Shape` has its [copy assignment `=deleted`](#Rc-copy-virtual), only the `Shape` part of `Triangle` is copied into the `Circle`.
|
||||
|
||||
|
||||
**Note**: Why not just require all owning refereces to be replaced by "smart pointers"?
|
||||
**Note**: Why not just require all owning references to be replaced by "smart pointers"?
|
||||
Changing from references to smart pointers implies code changes.
|
||||
We don't (yet) have smart references.
|
||||
Also, that may affect ABIs.
|
||||
|
@ -3795,7 +3795,7 @@ How would a maintainer know whether `j` was deliberately uninitialized (probably
|
|||
class B { // BAD
|
||||
string s1;
|
||||
public:
|
||||
B() { s1 = "Hello, "; } // BAD: default constuct followed by assignment
|
||||
B() { s1 = "Hello, "; } // BAD: default constructor followed by assignment
|
||||
// ...
|
||||
};
|
||||
|
||||
|
@ -3874,7 +3874,7 @@ By providing the factory function `Create()`, we make construction (on the free
|
|||
|
||||
**Example; bad**:
|
||||
|
||||
class Date { // BAD: repettive
|
||||
class Date { // BAD: repetitive
|
||||
int d;
|
||||
Month m;
|
||||
int y;
|
||||
|
@ -5279,7 +5279,7 @@ The two operations are still fundamentally different (and unrelated) but the nam
|
|||
|
||||
**Reason**: Implicit conversions can be essential (e.g., `double` to '`int`) but often cause surprises (e.g., `String` to C-style string).
|
||||
|
||||
**Note**: Prefer explicitly named conversions until a serious need is demonstracted.
|
||||
**Note**: Prefer explicitly named conversions until a serious need is demonstrated.
|
||||
By "serious need" we mean a reason that is fundamental in the application domain (such as an integer to complex number conversion)
|
||||
and frequently needed. Do not introduce implicit conversions (through conversion operators or non-`explicit` constructors)
|
||||
just to gain a minor convenience.
|
||||
|
@ -5862,7 +5862,7 @@ The use of the file handle (in `ifstream`) is simple, efficient, and safe.
|
|||
|
||||
**Enforcement**:
|
||||
|
||||
* Flag explicit allocations used to initialize pointers (problem: how many direct resouce allocations can we recognize?)
|
||||
* Flag explicit allocations used to initialize pointers (problem: how many direct resource allocations can we recognize?)
|
||||
|
||||
|
||||
<a name ="Rr-single alloc"></a>
|
||||
|
@ -5898,7 +5898,7 @@ Write your own factory wrapper if there is not one already.
|
|||
|
||||
**Enforcement**:
|
||||
|
||||
* Flag expressions with multiple explicit resource allocations (problem: how many direct resouce allocations can we recognize?)
|
||||
* Flag expressions with multiple explicit resource allocations (problem: how many direct resource allocations can we recognize?)
|
||||
|
||||
|
||||
<a name ="Rr-ap"></a>
|
||||
|
@ -6576,7 +6576,7 @@ We recommend keeping functions short, but that rule isn't universally adhered to
|
|||
<a name="Res-!CAPS"></a>
|
||||
### ES.9: Avoid `ALL_CAPS` names
|
||||
|
||||
**Reason**: Such names are commonly used for macros. Thus, ALL_CAPS name are vulnarable to unintend macro substitution.
|
||||
**Reason**: Such names are commonly used for macros. Thus, ALL_CAPS name are vulnerable to unintended macro substitution.
|
||||
|
||||
**Example**:
|
||||
|
||||
|
@ -7169,7 +7169,7 @@ rather than
|
|||
cout << v[i] << '\n';
|
||||
}
|
||||
|
||||
A human or a good static analyzer may determine that there really isn't a side efect on `v` in `f(&v[i])` so that the loop can be rewritten.
|
||||
A human or a good static analyzer may determine that there really isn't a side effect on `v` in `f(&v[i])` so that the loop can be rewritten.
|
||||
|
||||
"Messing with the loop variable" in the body of a loop is typically best avoided.
|
||||
|
||||
|
@ -7355,7 +7355,7 @@ Expressions manipulate values.
|
|||
|
||||
x = a+(b=f())+(c=g())*7; // bad: multiple assignments "hidden" in subexpressions
|
||||
|
||||
x = a&b+c*d&&e^f==7; // bad: relies on commonly misunderstool precedence rules
|
||||
x = a&b+c*d&&e^f==7; // bad: relies on commonly misunderstood precedence rules
|
||||
|
||||
x = x++ + x++ + ++x; // bad: undefined behavior
|
||||
|
||||
|
@ -7379,7 +7379,7 @@ Some of these expressions are unconditionally bad (e.g., they rely on undefined
|
|||
|
||||
**Enforcement**: Tricky. How complicated must an expression be to be considered complicated? Writing computations as statements with one operation each is also confusing. Things to consider:
|
||||
|
||||
* sideffects: sideffects on multiple non-local variables (for some definition of non-local) can be suspect, expecially if the sideefects are in separate subexpressions
|
||||
* side effects: side effects on multiple non-local variables (for some definition of non-local) can be suspect, especially if the side effects are in separate subexpressions
|
||||
* writes to aliased variables
|
||||
* more than N operators (and what should N be?)
|
||||
* reliance of subtle precedence rules
|
||||
|
@ -7545,7 +7545,7 @@ We also include lossy arithmetic casts, such as from a negative floating point t
|
|||
<a name="Res-nullptr"></a>
|
||||
### ES.47: Use `nullptr` rather than `0` or `NULL`
|
||||
|
||||
**Reason**: Readibility. Minimize surprises: `nullptr` cannot be confused with an `int`.
|
||||
**Reason**: Readability. Minimize surprises: `nullptr` cannot be confused with an `int`.
|
||||
|
||||
**Example**: Consider
|
||||
|
||||
|
@ -7629,7 +7629,7 @@ Such examples are often handled as well or better using `mutable` or an indirect
|
|||
<a name="Res-range-checking"></a>
|
||||
### ES.55: Avoid the need for range checking
|
||||
|
||||
**Reason**: Constructs that cannot oveflow, don't, and usually runs faster:
|
||||
**Reason**: Constructs that cannot overflow, don't, and usually runs faster:
|
||||
|
||||
**Example**:
|
||||
|
||||
|
@ -7721,7 +7721,7 @@ There can be code in the `...` part that causes the `delete` never to happen.
|
|||
**Note** Unfortunately, C++ uses signed integers for array subscripts and the standard library uses unsigned integers for container subscripts.
|
||||
This precludes consistency.
|
||||
|
||||
**Enforcement**: Complilers already know and sometimes warn.
|
||||
**Enforcement**: Compilers already know and sometimes warn.
|
||||
|
||||
|
||||
<a name="Res-unsigned"></a>
|
||||
|
@ -8243,7 +8243,7 @@ and to recover from an error every object not destroyed must be in a valid state
|
|||
<a name="Re-invariant"></a>
|
||||
### E.5: Let a constructor establish an invariant, and throw if it cannot
|
||||
|
||||
**Reason**: Leaving an object without its invariant aestablished is asking for trouble.
|
||||
**Reason**: Leaving an object without its invariant established is asking for trouble.
|
||||
Not all member function can be called.
|
||||
|
||||
**Example**:
|
||||
|
@ -8570,7 +8570,7 @@ Let cleanup actions on the unwinding path be handles by [RAII](#Re-raii).
|
|||
// ...
|
||||
}
|
||||
catch (...) {
|
||||
throw; // propagate excption
|
||||
throw; // propagate exception
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8720,7 +8720,7 @@ Concept use rule summary:
|
|||
* [T.10: Specify concepts for all template arguments](#Rt-concepts)
|
||||
* [T.11: Whenever possible use standard concepts](#Rt-std)
|
||||
* [T.12: Prefer concept names over `auto` for local variables](#Rt-auto)
|
||||
* [T.13: Prefer the shorhand notation for simple, single-type agument concepts](#Rt-shorthand)
|
||||
* [T.13: Prefer the shorthand notation for simple, single-type argument concepts](#Rt-shorthand)
|
||||
* ???
|
||||
|
||||
Concept definition rule summary:
|
||||
|
@ -8974,7 +8974,7 @@ Concept use rule summary:
|
|||
* [T.10: Specify concepts for all template arguments](#Rt-concepts)
|
||||
* [T.11: Whenever possible use standard concepts](#Rt-std)
|
||||
* [T.14: Prefer concept names over `auto`](#Rt-auto)
|
||||
* [T.15: Prefer the shorhand notation for simple, single-type agument concepts](Rt-shorthand)
|
||||
* [T.15: Prefer the shorthand notation for simple, single-type argument concepts](Rt-shorthand)
|
||||
* ???
|
||||
|
||||
Concept definition rule summary:
|
||||
|
@ -9041,7 +9041,7 @@ This is typically only needed when (as part of template metaprogramming code) we
|
|||
<a name="Rt-std"></a>
|
||||
### T.11: Whenever possible use standard concepts
|
||||
|
||||
**Reason**: "Standard" concepts (as provideded by the GSL, the ISO concepts TS, and hopefully soon the ISO standard itself)
|
||||
**Reason**: "Standard" concepts (as provided by the GSL, the ISO concepts TS, and hopefully soon the ISO standard itself)
|
||||
saves us the work of thinking up our own concepts, are better thought out than we can manage to do in a hurry, and improves interoperability.
|
||||
|
||||
**Note**: Unless you are creating a new generic library, most of the concepts you need will already be defined by the standard library.
|
||||
|
@ -9086,7 +9086,7 @@ It is better and simpler just to use `Sortable`:
|
|||
|
||||
|
||||
<a name="Rt-shorthand"></a>
|
||||
### T.13: Prefer the shorhand notation for simple, single-type agument concepts
|
||||
### T.13: Prefer the shorthand notation for simple, single-type argument concepts
|
||||
|
||||
**Reason**: Readability. Direct expression of an idea.
|
||||
|
||||
|
@ -9457,7 +9457,7 @@ Uniformity: `using` is syntactically similar to `auto`.
|
|||
tuple<int,string,double> t1 = {1,"Hamlet",3.14}; // explicit type
|
||||
auto t2 = make_tuple(1,"Ophelia"s,3.14); // better; deduced type
|
||||
|
||||
Note the use of the `s` suffix to ensire that the string is a `std::string`, rather than a C-style string.
|
||||
Note the use of the `s` suffix to ensure that the string is a `std::string`, rather than a C-style string.
|
||||
|
||||
**Note**: Since you can trivially write a `make_T` function, so could the compiler. Thus, `make_T` functions may become redundant in the future.
|
||||
|
||||
|
@ -9726,7 +9726,7 @@ There are three major ways to let calling code customize a template.
|
|||
f(t); // require f(/*T*/) be available in caller's cope or in T's namespace
|
||||
}
|
||||
|
||||
* Invoke a "trait" -- usually a type alias to compute a type, or a `constexpr` function to compute a value, or in rarer cases a traditioal traits template to be specialized on the user's type.
|
||||
* Invoke a "trait" -- usually a type alias to compute a type, or a `constexpr` function to compute a value, or in rarer cases a traditional traits template to be specialized on the user's type.
|
||||
|
||||
template<class T>
|
||||
void test(T t) {
|
||||
|
@ -10202,7 +10202,7 @@ Of course, range-for is better still where it does what you want.
|
|||
<a name="Rt-specialize-function"></a>
|
||||
### T.144: Don't specialize function templates
|
||||
|
||||
**Reason**: You can't partially specialize a function template per language rules. You can fully specialize a function tempalte but you almost certainly want to overload instead -- because function template specializations don't participate in overloading, they don't act as you probably wanted. Rarely, you should actualy specialize by delegating to a class template that you can specialize properly.
|
||||
**Reason**: You can't partially specialize a function template per language rules. You can fully specialize a function template but you almost certainly want to overload instead -- because function template specializations don't participate in overloading, they don't act as you probably wanted. Rarely, you should actually specialize by delegating to a class template that you can specialize properly.
|
||||
|
||||
**Example**:
|
||||
|
||||
|
@ -10211,7 +10211,7 @@ Of course, range-for is better still where it does what you want.
|
|||
**Exceptions**: If you do have a valid reason to specialize a function template, just write a single function template that delegates to a class template, then specialize the class template (including the ability to write partial specializations).
|
||||
|
||||
**Enforcement**:
|
||||
* Flag all specializations of a funciton template. Overload instead.
|
||||
* Flag all specializations of a function template. Overload instead.
|
||||
|
||||
|
||||
|
||||
|
@ -10675,7 +10675,7 @@ Many
|
|||
* focus on lower-level issues, such as the spelling of identifiers
|
||||
* are written by C++ novices
|
||||
* see "stopping programmers from doing unusual things" as their primary aim
|
||||
* aim at protability across many compilers (some 10 years old)
|
||||
* aim at portability across many compilers (some 10 years old)
|
||||
* are written to preserve decades old code bases
|
||||
* aims at a single application domain
|
||||
* are downright counterproductive
|
||||
|
@ -11468,7 +11468,7 @@ Comments are not updates as consistently as code.
|
|||
|
||||
auto x = m*v1 + vv; // multiply m with v1 and add the result to vv
|
||||
|
||||
**Enforcement**: Build an AI program that interprets colloqual English text and see if what is said could be better expressed in C++.
|
||||
**Enforcement**: Build an AI program that interprets colloquial English text and see if what is said could be better expressed in C++.
|
||||
|
||||
|
||||
<a name="Rl-comments intent"></a>
|
||||
|
@ -11651,7 +11651,7 @@ If you prefer CamelCase, you have to choose among different flavors of camelCase
|
|||
// ...
|
||||
}
|
||||
|
||||
**Note**: Some IDEs have their own opinios and adds distracting space.
|
||||
**Note**: Some IDEs have their own opinions and adds distracting space.
|
||||
|
||||
**Note**: We value well-placed whitespace as a significant help for readability. Just don't overdo it.
|
||||
|
||||
|
@ -11798,7 +11798,7 @@ In most circumstances, it is also impossible.
|
|||
This would be a set of changes across the whole code base, but would most likely have huge benefits.
|
||||
|
||||
Whichever way you choose, please note that the most advantages come with the highest conformance to the guidelines.
|
||||
The guidelines are not a random set of unrelated rules where you can srandomly pick and choose with an expectation of success.
|
||||
The guidelines are not a random set of unrelated rules where you can randomly pick and choose with an expectation of success.
|
||||
|
||||
We would dearly love to hear about experience and about tools used.
|
||||
Modernization can be much faster, simpler, and safer when supported with analysis tools and even code transformation tools.
|
||||
|
|
Loading…
Reference in New Issue
Block a user