update from master

This commit is contained in:
Sergey Zubkov
2024-05-11 22:10:56 -04:00
parent 554f61d507
commit fc65166a3a

View File

@@ -1,6 +1,6 @@
# <a name="main"></a>C++ Core Guidelines # <a name="main"></a>C++ Core Guidelines
February 15, 2024 May 11, 2024
Editors: Editors:
@@ -10,7 +10,7 @@ Editors:
This is a living document under continuous improvement. This is a living document under continuous improvement.
Had it been an open-source (code) project, this would have been release 0.8. Had it been an open-source (code) project, this would have been release 0.8.
Copying, use, modification, and creation of derivative works from this project is licensed under an MIT-style license. 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](LICENSE) file for details. Contributing to this project requires agreeing to a Contributor License. See the accompanying [LICENSE](https://github.com/isocpp/CppCoreGuidelines/blob/master/LICENSE) file for details.
We make this project available to "friendly users" to use, copy, modify, and derive from, hoping for constructive input. 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. Comments and suggestions for improvements are most welcome.
@@ -365,17 +365,17 @@ We do not limit our comment in the **Enforcement** sections to things we know ho
Tools that implement these rules shall respect the following syntax to explicitly suppress a rule: Tools that implement these rules shall respect the following syntax to explicitly suppress a rule:
[[gsl::suppress(tag)]] [[gsl::suppress("tag")]]
and optionally with a message (following usual C++11 standard attribute syntax): and optionally with a message (following usual C++11 standard attribute syntax):
[[gsl::suppress(tag, justification: "message")]] [[gsl::suppress("tag", justification: "message")]]
where where
* `tag` is the anchor name of the item where the Enforcement rule appears (e.g., for [C.134](#Rh-public) it is "Rh-public"), the * `"tag"` is a string literal with the anchor name of the item where the Enforcement rule appears (e.g., for [C.134](#Rh-public) it is "Rh-public"), the
name of a profile group-of-rules ("type", "bounds", or "lifetime"), name of a profile group-of-rules ("type", "bounds", or "lifetime"),
or a specific rule in a profile ([type.4](#Pro-type-cstylecast), or [bounds.2](#Pro-bounds-arrayindex)) or a specific rule in a profile ([type.4](#Pro-type-cstylecast), or [bounds.2](#Pro-bounds-arrayindex)). Any text that is not one of those should be rejected.
* `"message"` is a string literal * `"message"` is a string literal
@@ -1165,9 +1165,9 @@ Run a static analyzer to verify that your code follows the guidelines you want i
See See
* [Static analysis tools](???) * [Static analysis tools](https://en.wikipedia.org/wiki/List_of_tools_for_static_code_analysis)
* [Concurrency tools](#Rconc-tools) * [Concurrency tools](#Rconc-tools)
* [Testing tools](???) * [Testing tools](https://github.com/isocpp/CppCoreGuidelines/tree/master)
There are many other kinds of tools, such as source code repositories, build tools, etc., There are many other kinds of tools, such as source code repositories, build tools, etc.,
but those are beyond the scope of these guidelines. but those are beyond the scope of these guidelines.
@@ -2306,7 +2306,7 @@ Such examples are discussed in [[Str15]](http://www.stroustrup.com/resource-mode
So, we write a class So, we write a class
class Istream { [[gsl::suppress(lifetime)]] class Istream { [[gsl::suppress("lifetime")]]
public: public:
enum Opt { from_line = 1 }; enum Opt { from_line = 1 };
Istream() { } Istream() { }
@@ -3007,7 +3007,8 @@ When copying is cheap, nothing beats the simplicity and safety of copying, and f
For advanced uses (only), where you really need to optimize for rvalues passed to "input-only" parameters: For advanced uses (only), where you really need to optimize for rvalues passed to "input-only" parameters:
* If the function is going to unconditionally move from the argument, take it by `&&`. See [F.18](#Rf-consume). * If the function is going to unconditionally move from the argument, take it by `&&`. See [F.18](#Rf-consume).
* If the function is going to keep a copy of the argument, in addition to passing by `const&` (for lvalues), * If the function is going to keep a locally modifiable copy of the argument only for its own local use, taking it by value is fine
* If the function is going to keep a copy of the argument to pass to another destination (to another function, or store in a non-local location), in addition to passing by `const&` (for lvalues),
add an overload that passes the parameter by `&&` (for rvalues) and in the body `std::move`s it to its destination. Essentially this overloads a "will-move-from"; see [F.18](#Rf-consume). add an overload that passes the parameter by `&&` (for rvalues) and in the body `std::move`s it to its destination. Essentially this overloads a "will-move-from"; see [F.18](#Rf-consume).
* In special cases, such as multiple "input + copy" parameters, consider using perfect forwarding. See [F.19](#Rf-forward). * In special cases, such as multiple "input + copy" parameters, consider using perfect forwarding. See [F.19](#Rf-forward).
@@ -3663,7 +3664,7 @@ Importantly, that does not imply a transfer of ownership of the pointed-to objec
##### Note ##### Note
Positions can also be transferred by iterators, indices, and references. Positions can also be transferred by iterators, indices, and references.
A reference is often a superior alternative to a pointer [if there is no need to use `nullptr`](#Rf-ptr-ref) or [if the object referred to should not change](???). A reference is often a superior alternative to a pointer [if there is no need to use `nullptr`](#Rf-ptr-ref) or [if the object referred to should not change](#S-const).
##### Note ##### Note
@@ -3932,11 +3933,13 @@ value) of any assignment operator.
##### Reason ##### Reason
With guaranteed copy elision, it is now almost always a pessimization to expressly use `std::move` in a return statement. Returning a local variable implicitly moves it anyway.
An explicit `std::move` is always a pessimization, because it prevents Return Value Optimization (RVO),
which can eliminate the move completely.
##### Example, bad ##### Example, bad
S f() S bad()
{ {
S result; S result;
return std::move(result); return std::move(result);
@@ -3944,9 +3947,10 @@ With guaranteed copy elision, it is now almost always a pessimization to express
##### Example, good ##### Example, good
S f() S good()
{ {
S result; S result;
// Named RVO: move elision at best, move construction at worst
return result; return result;
} }
@@ -4148,8 +4152,6 @@ It's confusing. Writing `[=]` in a member function appears to capture by value,
// ... // ...
auto lambda = [=] { use(i, x); }; // BAD: "looks like" copy/value capture auto lambda = [=] { use(i, x); }; // BAD: "looks like" copy/value capture
// [&] has identical semantics and copies the this pointer under the current rules
// [=,this] and [&,this] are not much better, and confusing
x = 42; x = 42;
lambda(); // calls use(0, 42); lambda(); // calls use(0, 42);
@@ -4216,7 +4218,7 @@ Declaring a `...` parameter is sometimes useful for techniques that don't involv
##### Enforcement ##### Enforcement
* Issue a diagnostic for using `va_list`, `va_start`, or `va_arg`. * Issue a diagnostic for using `va_list`, `va_start`, or `va_arg`.
* Issue a diagnostic for passing an argument to a vararg parameter of a function that does not offer an overload for a more specific type in the position of the vararg. To fix: Use a different function, or `[[suppress(types)]]`. * Issue a diagnostic for passing an argument to a vararg parameter of a function that does not offer an overload for a more specific type in the position of the vararg. To fix: Use a different function, or `[[suppress("type")]]`.
### <a name="F-nesting"></a>F.56: Avoid unnecessary condition nesting ### <a name="F-nesting"></a>F.56: Avoid unnecessary condition nesting
@@ -5094,10 +5096,6 @@ There are two general categories of classes that need a user-defined destructor:
The default destructor does it better, more efficiently, and can't get it wrong. The default destructor does it better, more efficiently, and can't get it wrong.
##### Note
If the default destructor is needed, but its generation has been suppressed (e.g., by defining a move constructor), use `=default`.
##### Enforcement ##### Enforcement
Look for likely "implicit resources", such as pointers and references. Look for classes with destructors even though all their data members have destructors. Look for likely "implicit resources", such as pointers and references. Look for classes with destructors even though all their data members have destructors.
@@ -9539,7 +9537,7 @@ Returning a (raw) pointer imposes a lifetime management uncertainty on the calle
delete p; delete p;
} }
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" (see ["out" return values](#Rf-out)): In addition to suffering from the problem of [leak](#Rp-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" (see ["out" return values](#Rf-out)):
Gadget make_gadget(int n) Gadget make_gadget(int n)
{ {
@@ -9886,6 +9884,7 @@ This is more efficient:
`make_shared` gives a more concise statement of the construction. `make_shared` gives a more concise statement of the construction.
It also gives an opportunity to eliminate a separate allocation for the reference counts, by placing the `shared_ptr`'s use counts next to its object. It also gives an opportunity to eliminate a separate allocation for the reference counts, by placing the `shared_ptr`'s use counts next to its object.
It also ensures exception safety in complex expressions (in pre-C++17 code).
##### Example ##### Example
@@ -9905,7 +9904,7 @@ The `make_shared()` version mentions `X` only once, so it is usually shorter (as
##### Reason ##### Reason
`make_unique` gives a more concise statement of the construction. `make_unique` gives a more concise statement of the construction.
It also ensures exception safety in complex expressions. It also ensures exception safety in complex expressions (in pre-C++17 code).
##### Example ##### Example
@@ -12680,6 +12679,10 @@ wrong results, or memory corruption.
##### Note ##### Note
By pointer here we mean any indirection to an object, including equivalently an iterator or view.
##### Note
This rule is an obvious and well-known language rule, but can be hard to follow. This rule is an obvious and well-known language rule, but can be hard to follow.
It takes good coding style, library support, and static analysis to eliminate violations without major overhead. It takes good coding style, library support, and static analysis to eliminate violations without major overhead.
This is a major part of the discussion of [C++'s model for type- and resource-safety](#Stroustrup15). This is a major part of the discussion of [C++'s model for type- and resource-safety](#Stroustrup15).
@@ -20993,7 +20996,7 @@ Reference sections:
Libraries used have to have been approved for mission critical applications. Libraries used have to have been approved for mission critical applications.
Any similarities to this set of guidelines are unsurprising because Bjarne Stroustrup was an author of JSF++. Any similarities to this set of guidelines are unsurprising because Bjarne Stroustrup was an author of JSF++.
Recommended, but note its very specific focus. Recommended, but note its very specific focus.
* [MISRA C++ 2008: Guidelines for the use of the C++ language in critical systems](https://www.misra.org.uk/Buyonline/tabid/58/Default.aspx). * [MISRA C++:2023 Guidelines for the use C++17 in critical systems](https://misra.org.uk/product/misra-cpp2023/).
* [Using C++ in Mozilla Code](https://firefox-source-docs.mozilla.org/code-quality/coding-style/using_cxx_in_firefox_code.html). * [Using C++ in Mozilla Code](https://firefox-source-docs.mozilla.org/code-quality/coding-style/using_cxx_in_firefox_code.html).
As the name indicates, 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. As such, it is restrictive.
@@ -21155,7 +21158,7 @@ Enabling a profile is implementation defined; typically, it is set in the analys
To suppress enforcement of a profile check, place a `suppress` annotation on a language contract. For example: To suppress enforcement of a profile check, place a `suppress` annotation on a language contract. For example:
[[suppress(bounds)]] char* raw_find(char* p, int n, char x) // find x in p[0]..p[n - 1] [[suppress("bounds")]] char* raw_find(char* p, int n, char x) // find x in p[0]..p[n - 1]
{ {
// ... // ...
} }
@@ -22642,7 +22645,7 @@ Prevent leaks. Leaks can lead to performance degradation, mysterious error, syst
// ... // ...
}; };
This class is a resource handle. It manages the lifetime of the `T`s. To do so, `Vector` must define or delete [the set of special operations](???) (constructors, a destructor, etc.). This class is a resource handle. It manages the lifetime of the `T`s. To do so, `Vector` must define or delete [the set of special operations](#Rc-five) (constructors, a destructor, etc.).
##### Example ##### Example