views:

101

answers:

1

Possible Duplicate:
Overloading += in c++

Do I need to overload the += operator if I overload + or will the compiler know what to do?

Thanks.

+2  A: 

You need to overload both.

However, if you reverse the order you can reuse your code:

struct foo
{
    // this is the "core" operation, because it's mutating (changes this)
    foo& operator+=(const foo&)
    {
        // ...
        return *this;
    }

};

foo operator+(const foo& lhs, const foo& rhs)
{
    foo ret = lhs;
    ret += rhs;        
    return ret;
}

You make a copy, operate on that copy, and return it.

GMan
I don't believe that your last statement is true. In the case of `operator+` taking a copy inside the function tends to lead to fewer copies overall. The canonical form should (IMHO) be: `foo operator+(const foo ret += rhs; return ret; }` .
Charles Bailey
I like the form Charles Suggested as it is clearer to me. But I believe the form GMan is using allows for easier RVO for the compiler. So I think I will just need to get used to this new form (until compilers catch up then I can go back to the old form).
Martin York
I depends on a lot of factors but unless the compiler uses the internals of the `operator+=` (rather than just using it as a straight function call) my form will tend to result in fewer copies than the pass first param by value version. There are a couple of factors at work. First, from the function signature the caller cannot know that optimally the copy that it makes for the parameter could be the return value; this is known inside the function. Second, although `operator+=` returns a reference, the signature alone does not require this to be `*this`, even though we *know* it should be.
Charles Bailey
@Charles: I'm not sure I follow. My form makes a copy in the parameter, then makes a copy as it returns. Your form makes a copy in the body, then makes a copy as it returns. We have the same amount of copies, except my form allows copies to be elided when lhs is a temporary. And yeah, I except either the full definition to be available, or the use of a relatively modern compiler that does link-time optimization.
GMan
Your form allows the copy _in_ to be elided when it can be constructed in place. My form allows RVO; yours doesn't (without extra copmiler knowledge) because the caller makes the parameter copy (OK, might not be a copy) and doesn't know that it will be copied to the return value. I investigated using a recentish gcc (IIRC >4.2.0) and didn't find a situation where my form ever made more copies. This _doesn't_ mean that I don't believe that pass by value is always a bad idea; I believe it works well in (e.g.) copy and swap.
Charles Bailey
@Charles and GMan: I wrote a test, it looks like Charles wins on GCC. (You have to run it on your own; apparently CodePad uses -O0.) http://codepad.org/9ZfgSyO5
Potatoswatter
Although I do agree that GMan's theoretically should allow one temporary to be reused as an accumulator…
Potatoswatter
It always depends; if you already have an lvalue to use for the lhs, pass by value loses its advantage and is put at a potential disadvantage. If you're creating a temporary for the lhs, pass by value can have an advantage, but might require inlining of `op+` and possibly `op+=` to make it count (in my experiments I didn't manage to get this to work). Mine _definitely_ holds it's advantage if `op+=` is not inline and part of a shared object / dll interface and `op+` is supplied as an inline helper (i.e. no possiblity of a class of link time optimizations). Either way, it's not cut and dry.
Charles Bailey
@Potato @Charles: Nice, I think your version is better then, since it never loses.
GMan