If you're thinking of a custom, move-supported string class, the right way to use each combination of argument value categories is:
S operator+(S const& lhs, S const& rhs); S operator+(S && lhs, S const& rhs); S operator+(S const& lhs, S && rhs); S operator+(S && lhs, S && rhs);
Functions return prvalue instead of xvalue. The return value of x is usually a very dangerous thing. - std :: move and std :: forward are obvious exceptions. If you returned the link to rvalue, you would break the code, for example:
for (char c : my_string + other_string) {
This loop behaves (according to 6.5.4 / 1 in N3092), as if the code:
auto&& range = my_string + other_string;
This, in turn, leads to a deceived link. The temporary object does not expire because your + operator does not return a prvalue value. Returning objects by value is excellent. This will create temporary objects, but these objects have rvalues, so we can steal their resources to make them very efficient.
Secondly, your code also should not compile for the same reason that it will not compile:
int&& foo(int&& x) { return x; }
Inside the body of the function x, there is an lvalue, and you cannot initialize the "return value" (in this case, the rvalue reference) with the expression lvalue. So, you will need an explicit listing.
Third, you are missing const & + const & overload. If both arguments are equal to lvalues, the compiler will not find a suitable + operator in your case.
If you do not want so many overloads, you can also write:
S operator+(S value, S const& x) { value += x; return value; }
I intentionally did not write return value+=x; , because this statement probably returns an lvalue reference that would lead to a copy of the return value construct. With the two lines that I wrote, the return value will move through the value.
S x = a + b + c + d;
At least this case is very effective because there is no need for unnecessary copying, even if the compiler cannot exclude copies - thanks to the line class with support for moving. In fact, with a class like std :: string, you can use the swap quick exchange function and make it efficient in C ++ 03 if you have a reasonably smart compiler (like GCC):
S operator+(S value, S const& x)
See David Abraham's article Want speed? Pass by value . But these simple operators will not be so efficient:
S x = a + (b + (c + d));
Here the left side of the operator is always the value of l. Since the + operator takes its left side by value, this leads to many copies. Four overloads from above also do a great job with this example.
It has been some time since I read Linus' old story. If he complained about unnecessary copies in relation to std :: string, this complaint is no longer valid in C ++ 0x, but it was almost invalid before. You can efficiently concatenate many lines in C ++ 03:
S result = a; result += b; result += c; result += d;
But in C ++ 0x, you can also use operator + and std :: move. It will also be very effective.
I really looked at the Git source code and its string management (strbuf.h). It looks well thought out. With the exception of the disconnect / attach function, you get the same thing with the std :: string movement turned on with the obvious advantage that the resource that it automatically controls the class itself, as opposed to the user who needs to remember to call the correct functions on (strbuf_init , strbuf_release).