F.20 extract unrelated parts into new rule, F.49

closes #1862
This commit is contained in:
Sergey Zubkov
2022-10-06 19:05:38 -04:00
parent 7ad62600f1
commit a217a9ff71

View File

@@ -1,7 +1,6 @@
# <a name="main"></a>C++ Core Guidelines
September 23, 2022
October 6, 2022
Editors:
@@ -2378,6 +2377,7 @@ Parameter passing semantic rules:
* [F.46: `int` is the return type for `main()`](#Rf-main)
* [F.47: Return `T&` from assignment operators](#Rf-assignment-op)
* [F.48: Don't `return std::move(local)`](#Rf-return-move-local)
* [F.49: Don't return `const T`](#Rf-return-const)
Other function rules:
@@ -3157,25 +3157,6 @@ If you have multiple values to return, [use a tuple](#Rf-out-multi) or similar m
A `struct` of many (individually cheap-to-move) elements might be in aggregate expensive to move.
##### Note
It is not recommended to return a `const` value.
Such older advice is now obsolete; it does not add value, and it interferes with move semantics.
const vector<int> fct(); // bad: that "const" is more trouble than it is worth
void g(vector<int>& vx)
{
// ...
fct() = vx; // prevented by the "const"
// ...
vx = fct(); // expensive copy: move semantics suppressed by the "const"
// ...
}
The argument for adding `const` to a return value is that it prevents (very rare) accidental access to a temporary.
The argument against is that it prevents (very frequent) use of move semantics.
##### Exceptions
* For non-concrete types, such as types in an inheritance hierarchy, return the object by `unique_ptr` or `shared_ptr`.
@@ -3218,7 +3199,6 @@ The return value optimization doesn't handle the assignment case, but the move a
##### Enforcement
* Flag reference to non-`const` parameters that are not read before being written to and are a type that could be cheaply returned; they should be "out" return values.
* Flag returning a `const` value. To fix: Remove `const` to return a non-`const` value instead.
### <a name="Rf-out-multi"></a>F.21: To return multiple "out" values, prefer returning a struct or tuple
@@ -3910,7 +3890,6 @@ This was primarily to avoid code of the form `(a = b) = c` -- such code is not c
This should be enforced by tooling by checking the return type (and return
value) of any assignment operator.
### <a name="Rf-return-move-local"></a>F.48: Don't `return std::move(local)`
##### Reason
@@ -3937,6 +3916,35 @@ With guaranteed copy elision, it is now almost always a pessimization to express
This should be enforced by tooling by checking the return expression .
### <a name="Rf-return-const"></a>F.49: Don't return `const T`
##### Reason
It is not recommended to return a `const` value.
Such older advice is now obsolete; it does not add value, and it interferes with move semantics.
##### Example
const vector<int> fct(); // bad: that "const" is more trouble than it is worth
void g(vector<int>& vx)
{
// ...
fct() = vx; // prevented by the "const"
// ...
vx = fct(); // expensive copy: move semantics suppressed by the "const"
// ...
}
The argument for adding `const` to a return value is that it prevents (very rare) accidental access to a temporary.
The argument against is that it prevents (very frequent) use of move semantics.
**See also**: [F.20, the general item about "out" output values](#Rf-out)
##### Enforcement
* Flag returning a `const` value. To fix: Remove `const` to return a non-`const` value instead.
### <a name="Rf-capture-vs-overload"></a>F.50: Use a lambda when a function won't do (to capture local variables, or to write a local function)