Skip to content

Commit 9da24c4

Browse files
committed
Explain returning rvalue references, closes #3
1 parent ee489cb commit 9da24c4

File tree

1 file changed

+53
-4
lines changed

1 file changed

+53
-4
lines changed

README.md

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,16 @@
99

1010
The Art of C++ / Operators is a zero-dependency C++11 single-header library that provides highly efficient, move aware operators for arithmetic data types.
1111

12-
### Table of content
12+
### Table of Content
1313

1414
[Preface](#preface)<br/>
1515
[Rationale](#rationale)<br/>
1616
[Example](#example)<br/>
1717
[Requirements](#requirements)<br/>
1818
[Installation](#installation)<br/>
19-
[Provided templates](#provided-templates)<br/>
19+
[Provided Templates](#provided-templates)<br/>
2020
[Commutativity](#commutativity)<br/>
21+
[RValue References](#rvalue-references)<br/>
2122
[noexcept](#noexcept)<br/>
2223
[License](#license)
2324

@@ -107,7 +108,7 @@ Requires C++11 or newer. Tested with:
107108

108109
* GCC 4.7+
109110
* Clang 3.2+
110-
* Visual Studio 2015
111+
* Visual Studio 2015+
111112

112113
Remember to enable C++11, e.g., provide `-std=c++11` or similar options.
113114

@@ -121,7 +122,7 @@ Remember to enable C++11, e.g., provide `-std=c++11` or similar options.
121122
The Art of C++ / Operators is a single-header library. There is nothing to build or install,
122123
just copy the header somewhere and include it in your code.
123124

124-
## Provided templates
125+
## Provided Templates
125126

126127
The following table gives an overview of the available templates.
127128
Note that the "Provides" and "Requires" columns are just a basic overview.
@@ -832,6 +833,54 @@ For the two-argument version, `commutative_{OP}< T, U >` provides the operators
832833
of both `{OP}< T, U >` and `{OP}_left< T, U >`, again the return type indicates
833834
those cases where an extra temporary is avoided.
834835

836+
## RValue References
837+
838+
As you can see above, several overloads of some operators return rvalue references.
839+
This helps to eliminate temporaries in more complicated expressions, but some people
840+
consider it dangerous. The argument against returning rvalue references usually
841+
is something like:
842+
843+
```c++
844+
const auto& result = a + b + c;
845+
```
846+
847+
where they expect a temporary to be returned from the expression `a + b + c`,
848+
and the lifetime of the temporary can be extended by binding it to a reference.
849+
850+
While this would work if an actual temporary value is returned, it does not work with
851+
the second operator `+` returning an rvalue reference to the *intermediate* temporary
852+
created by the first operator `+`.
853+
854+
I consider the above code bad style that has no place in modern C++. It should be
855+
replaced by
856+
857+
```c++
858+
const auto result = a + b + c;
859+
```
860+
861+
and the problem goes away. Also, if you *expect* an expression to return a temporary
862+
value, but you don't *verify* your assumption, it is your fault for basing your code
863+
on those assumptions.
864+
865+
There is, however, one problem where the above binding to a references happens behind
866+
the scenes, i.e. without being immediately visible. It may happen if you are using
867+
a range-based for-loop. The problem in this case is not limited to returning rvalue
868+
references, hence you should always make sure that you do not mix any kind of expression
869+
other than directly naming a variable when using a range-based for-loop. Example:
870+
871+
```c++
872+
// instead of this:
873+
for( const auto& e : a + b + c ) { ... }
874+
875+
// always use something like this:
876+
const auto r = a + b + c;
877+
for( const auto& e : r ) { ... }
878+
```
879+
880+
With all that said, you can disable returning rvalue references by defining
881+
`TAO_OPERATORS_NO_RVALUE_REFERENCE_RESULTS`. If it is set, all operators will
882+
return a value (an rvalue) instead of rvalue references.
883+
835884
## noexcept
836885
837886
If your compiler does not support `noexcept`, the following might be a viable

0 commit comments

Comments
 (0)