[F.21] address returning expensive-to-copy tuples (closes #1945)

This commit is contained in:
Sergey Zubkov
2022-09-23 00:04:32 -04:00
parent dfaecb2e75
commit f25df31132

View File

@@ -3155,7 +3155,7 @@ Prefer using a named struct where there are semantics to the returned value. Oth
tuple<int, string> f(const string& input) tuple<int, string> f(const string& input)
{ {
// ... // ...
return make_tuple(status, something()); return {status, something()};
} }
C++98's standard library already used this style, because a `pair` is like a two-element `tuple`. C++98's standard library already used this style, because a `pair` is like a two-element `tuple`.
@@ -3203,7 +3203,7 @@ To compare, if we passed out all values as return values, we would something lik
{ {
string s; string s;
is >> s; is >> s;
return {is, s}; return {is, move(s)};
} }
for (auto p = get_string(cin); p.first; ) { for (auto p = get_string(cin); p.first; ) {
@@ -3236,6 +3236,29 @@ The overly-generic `pair` and `tuple` should be used only when the value returne
Another example, use a specific type along the lines of `variant<T, error_code>`, rather than using the generic `tuple`. Another example, use a specific type along the lines of `variant<T, error_code>`, rather than using the generic `tuple`.
##### Note
When the tuple to be returned is initialized from local variables that are expensive to copy,
explicit `move` may be helpful to avoid copying:
pair<LargeObject, LargeObject> f(const string& input)
{
LargeObject large1 = g(input);
LargeObject large2 = h(input);
// ...
return { move(large1), move(large2) }; // no copies
}
Alternatively,
pair<LargeObject, LargeObject> f(const string& input)
{
// ...
return { g(input), h(input) }; // no copies, no moves
}
Note this is different from the `return move(...)` anti-pattern from [ES.56](#Res-move)
##### Enforcement ##### Enforcement
* Output parameters should be replaced by return values. * Output parameters should be replaced by return values.