Skip to content

Commit 7d3ff3c

Browse files
committed
Merged F.23 into F.15 (issue #1)
1 parent 59eacc8 commit 7d3ff3c

File tree

1 file changed

+20
-31
lines changed

1 file changed

+20
-31
lines changed

CppCoreGuidelines.md

Lines changed: 20 additions & 31 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.23: Use `T&` for an out-parameter that is expensive to move (only)](#Rf-T-return-out)
17891788
* [F.24: Use a `TP&&` parameter when forwarding (only)](#Rf-pass-ref-ref)
17901789
* [F.25: Use a `T&&` parameter together with `move` for rare optimization opportunities](#Rf-pass-ref-move)
17911790
* [F.26: Use a `unique_ptr<T>` to transfer ownership where a pointer is needed](#Rf-unique_ptr)
@@ -2196,23 +2195,39 @@ If you really feel the need for an optimization beyond the common techniques, me
21962195
![Normal parameter passing table](./param-passing-normal.png "Normal parameter passing")
21972196

21982197
**For an "output-only" value:** Prefer return values to output parameters.
2199-
This includes large objects like standard containers that use implicit move operations for performance and to avoid explicit memory management.
2198+
This includes large objects like standard containers that use implicit move operations for performance and to avoid explicit memory management. A return value is harder to miss and harder to misuse than a `T&` (an in-out parameter).
22002199
If you have multiple values to return, [use a tuple](#Rf-T-multi) or similar multi-member type.
22012200

22022201
##### Example
22032202

2204-
vector<const int*> find_all(const vector<int>&, int x); // return pointers to elements with the value x
2203+
vector<const int*> find_all(const vector<int>&, int x); // OK: return pointers to elements with the value x
22052204

2206-
##### Example, bad
2205+
void find_all(const vector<int>&, vector<const int*>& out, int x); // Bad: place pointers to elements with value x in out
22072206

2208-
void find_all(const vector<int>&, vector<const int*>& out, int x); // place pointers to elements with value x in out
2207+
##### Note
2208+
2209+
A struct of many (individually cheap-to-move) elements may be in aggregate expensive to move.
22092210

22102211
##### Exceptions
22112212

22122213
* For non-value types, such as types in an inheritance hierarchy, return the object by `unique_ptr` or `shared_ptr`.
22132214
* If a type is expensive to move (e.g., `array<BigPOD>`), consider allocating it on the free store and return a handle (e.g., `unique_ptr`), or passing it in a non-`const` reference to a target object to fill (to be used as an out-parameter).
22142215
* In the special case of allowing a caller to reuse an object that carries capacity (e.g., `std::string`, `std::vector`) across multiple calls to the function in an inner loop, treat it as an in/out parameter instead and pass by `&`. This is one use of the more generally named "caller-allocated out" pattern.
22152216

2217+
##### Example
2218+
2219+
struct Package { // exceptional case: expensive-to-move object
2220+
char header[16];
2221+
char load[2024 - 16];
2222+
};
2223+
2224+
Package fill(); // Bad: large return value
2225+
void fill(Package&); // OK
2226+
2227+
int val(); // OK
2228+
void val(int&); // Bad: Is val reading its argument
2229+
2230+
22162231
**For an "in-out" parameter:** Pass by non-`const` reference. This makes it clear to callers that the object is assumed to be modified.
22172232

22182233
##### Example
@@ -2443,32 +2458,6 @@ When I call `length(s)` should I test for `s == nullptr` first? Should the imple
24432458
**See also**: [Support library](#S-gsl).
24442459

24452460

2446-
### <a name="Rf-T-return-out"></a> F.23: Use `T&` for an out-parameter that is expensive to move (only)
2447-
2448-
##### Reason
2449-
2450-
A return value is harder to miss and harder to misuse than a `T&` (an in-out parameter); [see also](#Rf-T-return); [see also](#Rf-T-multi).
2451-
2452-
##### Example
2453-
2454-
struct Package {
2455-
char header[16];
2456-
char load[2024 - 16];
2457-
};
2458-
2459-
Package fill(); // Bad: large return value
2460-
void fill(Package&); // OK
2461-
2462-
int val(); // OK
2463-
void val(int&); // Bad: Is val reading its argument
2464-
2465-
##### Enforcement
2466-
2467-
Hard to choose a cutover value for the size of the value returned.
2468-
2469-
##### Note
2470-
A struct of many (individually cheap-to-move) elements may be in aggregate expensive to move.
2471-
24722461
### <a name="Rf-pass-ref-ref"></a> F.24: Use a `TP&&` parameter when forwarding (only)
24732462

24742463
##### Reason

0 commit comments

Comments
 (0)