From 7615d3076df3c5888c63ca5df3b7d5897cd613d9 Mon Sep 17 00:00:00 2001 From: Titus Winters Date: Tue, 15 Dec 2015 11:43:58 -0500 Subject: [PATCH 1/2] Add F.47 - Assignment operators return T& As discussed in https://github.com/isocpp/CppCoreGuidelines/issues/422 --- CppCoreGuidelines.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/CppCoreGuidelines.md b/CppCoreGuidelines.md index ff31d95..a6f8b85 100644 --- a/CppCoreGuidelines.md +++ b/CppCoreGuidelines.md @@ -2873,6 +2873,38 @@ Declaring `main` (the one global `main` of a program) `void` limits portability. * The compiler should do it * If the compiler doesn't do it, let tools flag it +### F.46: Return `T&` from assignment operators. + +##### Reason + +The convention for operator overloads (especially on value types) is for +`operator=(const T&)` to perform the assignment and then return (non-const) +`*this`. This ensures consistency with standard library types and follows the +principle of "do as the ints do." + +##### Note + +Historically there was some guidance to make the assignment operator return +`const T&`. This was primarily to avoid code of the form `(a=b)=c` - such code +is not common enough to warrant violating consistency with standard types. + +##### Example + + class Foo + { + public: + ... + Foo& operator=(const Foo& rhs) { + // Copy members. + ... + return *this; + } + }; + +##### Enforcement + +This should be enforced by tooling by checking the return type (and return +value) of any assignment operator. ### F.50: Use a lambda when a function won't do (to capture local variables, or to write a local function) From fea884184e7f9276dd2f87fc958daa6b0f70cd06 Mon Sep 17 00:00:00 2001 From: Titus Winters Date: Tue, 15 Dec 2015 11:48:04 -0500 Subject: [PATCH 2/2] Blend new F.47 into existing text. --- CppCoreGuidelines.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CppCoreGuidelines.md b/CppCoreGuidelines.md index a6f8b85..9a72d74 100644 --- a/CppCoreGuidelines.md +++ b/CppCoreGuidelines.md @@ -1820,6 +1820,7 @@ Value return semantic rules: * [F.44: Return a `T&` when "returning no object" isn't an option](#Rf-return-ref) * [F.45: Don't return a `T&&`](#Rf-return-ref-ref) * [F.46: `int` is the return type for `main()`](#Rf-main) +* [F.47: Return `T&` from assignment operators.](#Rf-assignment-op) Other function rules: @@ -2258,7 +2259,7 @@ For advanced uses (only), where you really need to optimize for rvalues passed t Avoid "esoteric techniques" such as: * Passing arguments as `T&&` "for efficiency". Most rumors about performance advantages from passing by `&&` are false or brittle (but see [F.25](#Rf-pass-ref-move).) -* Returning `const T&` from assignments and similar operations. +* Returning `const T&` from assignments and similar operations (see [F.47](#Rf-assignment-op).) ##### Example @@ -2873,7 +2874,7 @@ Declaring `main` (the one global `main` of a program) `void` limits portability. * The compiler should do it * If the compiler doesn't do it, let tools flag it -### F.46: Return `T&` from assignment operators. +### F.47: Return `T&` from assignment operators. ##### Reason