22

Following the advice given in this answer, I have overloaded the + operator in my simple Point class as follows (the += overload works fine).

Point operator+ (Point p1, const Point& p2)
{
    return std::move(p1 += p2);
}

But I get an error saying

overloaded 'operator+' must be a unary or binary operator (has 3 parameters)

What is wrong?

Community
  • 1
  • 1
learnvst
  • 15,455
  • 16
  • 74
  • 121
  • 3
    The advice is wrong. [Never move return values](http://stackoverflow.com/questions/4986673/c11-rvalues-and-move-semantics-confusion), this is a unnecessary code bloat and makes them even slower. – ipc Nov 25 '12 at 19:09
  • @ipc That was something else I was hoping to spark a little debate about – learnvst Nov 25 '12 at 19:11
  • 3
    @ipc without a move that would have copied. He would have to split his code into two lines to achieve the same effect (it is not allowed to do NRVO from a function parameter, but the rvalue trasformation is still done). – Johannes Schaub - litb Nov 25 '12 at 21:45
  • @JohannesSchaub-litb Yes, I need to `p1+=p2; return p1;` now, but I would also need to do the same with `move` – learnvst Nov 25 '12 at 22:03

3 Answers3

25

It sounds like you have declared your operator as a member function. A member function takes an implicit first parameter, meaning your operator now takes three parameters. You can fix this by making it a non-member function.

In any case, it is preferable to declare it as a non-member, to ensure symmetry between the LHS and the RHS of the operation.

As for std::move, it is in the <utility> header. Although I can't see the reason to use it here.

ildjarn
  • 62,044
  • 9
  • 127
  • 211
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
17

You want to do either:

// Member function, performs (*this + right)
Point operator+ (Point & right)

or

// Free function, performs (left + right)
Point operator+ (const Point &left, const Point& right)
Drew Dormann
  • 59,987
  • 13
  • 123
  • 180
  • 1
    What's the need for `friend` here? – Lightness Races in Orbit Nov 25 '12 at 19:01
  • 4
    @LightnessRacesinOrbit a hack so you can declare the function inside the class declaration :-) Nothing to do with friendship. – juanchopanza Nov 25 '12 at 19:07
  • 3
    I must add, I don't think `friend` is needed here at all, it is just confusing. Plus the signature change is significant here. – juanchopanza Nov 25 '12 at 19:11
  • @juanchopanza declaring the function within a class implies access to private members. That has already been done. Using `friend` removes the implicit `this` from that situation. – Drew Dormann Nov 25 '12 at 19:17
  • But you don't need access to private members. Therefore, you shouldn't have any. Basic principles of encapsulation... – Lightness Races in Orbit Nov 25 '12 at 19:23
  • I think it was a programming error to declare it as a member. In any case, `+=` is usually public. – juanchopanza Nov 25 '12 at 19:40
  • @juanchopanza I'm sure that you're right about that. I think my answer directly answered the question with the least changes, but perhaps a note would have helped along the lines of "You should ask a new question about why this function should be declared outside of the class" – Drew Dormann Nov 26 '12 at 17:48
3

You made the operator a member function, meaning it actually has three parameters when you include the implicit first this parameter.

Either:

  • Use *this rather than p1 and get rid of that first parameter, or
  • Make the operator overload a free function (instead of a member) — this is preferred.
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055