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 # <a name="main"></a>C++ Core Guidelines
September 23, 2022 October 6, 2022
Editors: Editors:
@@ -2378,6 +2377,7 @@ Parameter passing semantic rules:
* [F.46: `int` is the return type for `main()`](#Rf-main) * [F.46: `int` is the return type for `main()`](#Rf-main)
* [F.47: Return `T&` from assignment operators](#Rf-assignment-op) * [F.47: Return `T&` from assignment operators](#Rf-assignment-op)
* [F.48: Don't `return std::move(local)`](#Rf-return-move-local) * [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: 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. 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 ##### Exceptions
* For non-concrete types, such as types in an inheritance hierarchy, return the object by `unique_ptr` or `shared_ptr`. * 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 ##### 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 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 ### <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 This should be enforced by tooling by checking the return type (and return
value) of any assignment operator. value) of any assignment operator.
### <a name="Rf-return-move-local"></a>F.48: Don't `return std::move(local)` ### <a name="Rf-return-move-local"></a>F.48: Don't `return std::move(local)`
##### Reason ##### 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 . 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) ### <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)