learnvst
learnvst

Reputation: 16195

overloaded 'operator+' must be a unary or binary operator error

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?

Upvotes: 25

Views: 32964

Answers (4)

Yong Yang
Yong Yang

Reputation: 126

The member function implicitly takes this as a parameter,

So take operator+ as a member function, should only have one explicit parameter:

void Point::operator+(const Point& rhs)
{
    ...
}

And if take operator+ as a non-member function, sholud have two parameters:

Point operator+(Point& lhs, const Point& rhs)
{
    ...
}

And for std::move, it casts rvalue reference to rvalue, and move lhs into return value, only reasonable to use when lhs passed as rvalue reference:

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

Or you may consider use std::forward, if pass lhs as lvalue reference and rvalue reference both exits:

template<
    typename T,
    typename = typename std::enable_if<
        std::is_same<Point, typename std::decay<T>::type>::value
        >::type>
Point
operator+(T&& lhs,  const Point& rhs)
{
    lhs += rhs;
    return std::forward<T>(lhs);  // move rvalue into return value, copy lvalue
}

Refer to Effective Modern C++ by Scott Meyers item 25: Use std::move on rvalue references, std::forward on universal references.

Upvotes: 0

Drew Dormann
Drew Dormann

Reputation: 63775

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)

Upvotes: 17

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385144

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.

Upvotes: 3

juanchopanza
juanchopanza

Reputation: 227410

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.

Upvotes: 29

Related Questions