Skip to content

Commit 89bf79e

Browse files
committed
Merged F.24 into F.15 (issue #1)
1 parent 7d3ff3c commit 89bf79e

File tree

1 file changed

+14
-20
lines changed

1 file changed

+14
-20
lines changed

CppCoreGuidelines.md

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1785,7 +1785,6 @@ Argument passing rules:
17851785
* [F.17: Use a `not_null<T>` to indicate "null" is not a valid value](#Rf-nullptr)
17861786
* [F.18: Use a `span<T>` or a `span_p<T>` to designate a half-open sequence](#Rf-range)
17871787
* [F.19: Use a `zstring` or a `not_null<zstring>` to designate a C-style string](#Rf-string)
1788-
* [F.24: Use a `TP&&` parameter when forwarding (only)](#Rf-pass-ref-ref)
17891788
* [F.25: Use a `T&&` parameter together with `move` for rare optimization opportunities](#Rf-pass-ref-move)
17901789
* [F.26: Use a `unique_ptr<T>` to transfer ownership where a pointer is needed](#Rf-unique_ptr)
17911790
* [F.27: Use a `shared_ptr<T>` to share ownership](#Rf-shared_ptr)
@@ -2181,9 +2180,9 @@ Pure functions are easier to reason about, sometimes easier to optimize (and eve
21812180

21822181
Not possible.
21832182

2184-
## <a name="SS-call"></a> F.call: Argument passing
2183+
## <a name="SS-call"></a> F.call: Parameter passing
21852184

2186-
There are a variety of ways to pass arguments to a function and to return values.
2185+
There are a variety of ways to pass parameters to a function and to return values.
21872186

21882187
### <a name="Rf-conventional"></a> Rule F.15: Prefer simple and conventional ways of passing information
21892188

@@ -2314,12 +2313,24 @@ A reference may be assumed to refer to a valid object (language rule).
23142313
There is no (legitimate) "null reference."
23152314
If you need the notion of an optional value, use a pointer, `std::optional`, or a special value used to denote "no value."
23162315

2316+
2317+
**For an "forwarded" value:** If the object is to be passed onward to other code and not directly used by this function, we want to make this function agnostic to the argument `const`-ness and rvalue-ness. In that case, and only that case, make the parameter `TP&&` where `TP` is a template type parameter -- it both *ignores* and *preserves* `const`-ness and rvalue-ness. Therefore any code that uses a `T&&` is implicitly declaring that it itself doesn't care about the variable's `const`'-ness and rvalue-ness (because it is ignored), but that intends to pass the value onward to other code that does care about `const`-ness and rvalue-ness (because it is preserved). When used as a parameter `TP&&` is safe because any temporary objects passed from the caller will live for the duration of the function call. A parameter of type `TP&&` should essentially always be passed onward via `std::forward` in the body of the function.
2318+
2319+
##### Example
2320+
2321+
template <class F, class... Args>
2322+
inline auto invoke(F&& f, Args&&... args) {
2323+
return forward<F>(f)(forward<Args>(args)...);
2324+
}
2325+
2326+
23172327
##### Enforcement
23182328

23192329
* (Simple) ((Foundation)) Warn when a parameter being passed by value has a size greater than `4 * sizeof(int)`.
23202330
Suggest using a `const` reference instead.
23212331
* (Simple) ((Foundation)) Warn when a `const` parameter being passed by reference has a size less than `3 * sizeof(int)`. Suggest passing by value instead.
23222332
* (Moderate) ((Foundation)) Warn about functions with non-`const` reference arguments that do *not* write to them.
2333+
* Flag a function that takes a `TP&&` parameter (where `TP` is a template type parameter name) and uses it without `std::forward`.
23232334

23242335

23252336
**See also**: [implicit arguments](#Ri-explicit).
@@ -2458,23 +2469,6 @@ When I call `length(s)` should I test for `s == nullptr` first? Should the imple
24582469
**See also**: [Support library](#S-gsl).
24592470

24602471

2461-
### <a name="Rf-pass-ref-ref"></a> F.24: Use a `TP&&` parameter when forwarding (only)
2462-
2463-
##### Reason
2464-
2465-
When `TP` is a template type parameter, `TP&&` is a forwarding reference -- it both *ignores* and *preserves* `const`'ness and rvalue-ness. Therefore any code that uses a `T&&` is implicitly declaring that it itself doesn't care about the variable's `const`'-ness and rvalue-ness (because it is ignored), but that intends to pass the value onward to other code that does care about `const`'-ness and rvalue-ness (because it is preserved). When used as a parameter `TP&&` is safe because any temporary objects passed from the caller will live for the duration of the function call. A parameter of type `TP&&` should essentially always be passed onward via `std::forward` in the body of the function.
2466-
2467-
##### Example
2468-
2469-
template <class F, class... Args>
2470-
inline auto invoke(F&& f, Args&&... args) {
2471-
return forward<F>(f)(forward<Args>(args)...);
2472-
}
2473-
2474-
##### Enforcement
2475-
2476-
Flag a function that takes a `TP&&` parameter (where `TP` is a template type parameter name) and uses it without `std::forward`.
2477-
24782472
### <a name="Rf-pass-ref-move"></a> F.25: Use a `T&&` parameter together with `move` for rare optimization opportunities
24792473

24802474
##### Reason

0 commit comments

Comments
 (0)