From f25df3113299afd23164cd05558697ca7b90b6f2 Mon Sep 17 00:00:00 2001 From: Sergey Zubkov Date: Fri, 23 Sep 2022 00:04:32 -0400 Subject: [PATCH] [F.21] address returning expensive-to-copy tuples (closes #1945) --- CppCoreGuidelines.md | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/CppCoreGuidelines.md b/CppCoreGuidelines.md index 9e553b7..df0aa3f 100644 --- a/CppCoreGuidelines.md +++ b/CppCoreGuidelines.md @@ -3155,7 +3155,7 @@ Prefer using a named struct where there are semantics to the returned value. Oth tuple 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`. @@ -3203,7 +3203,7 @@ To compare, if we passed out all values as return values, we would something lik { string s; is >> s; - return {is, s}; + return {is, move(s)}; } 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`, 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 f(const string& input) + { + LargeObject large1 = g(input); + LargeObject large2 = h(input); + // ... + return { move(large1), move(large2) }; // no copies + } + +Alternatively, + + pair 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 * Output parameters should be replaced by return values.