jasonline
jasonline

Reputation: 9056

Question on overloading operator+

Consider the following code:


class A
{
public:
    A& operator=( const A& );
    const A& operator+( const A& );
    const A& operator+( int m );
};

int main()
{
    A a;
    a = ( a + a ) + 5;   // error: binary '+' : no operator found which takes a left-hand operand of type 'const A'
}

Can anyone explain why the above is returned as an error?

"( a + a )" calls "const A& operator+( const A& )" and returns a constant reference which is then passed to "const A& operator+( int m )" if I'm not mistaken.

How can one fix the above error (without creating a global binary operator+ or a constructor that accepts an int) such that the statement inside main() is allowed?

Upvotes: 3

Views: 2024

Answers (6)

sbi
sbi

Reputation: 224049

The problem is that (a+a) returns a so-called rvalue (basically a fancy term for a temporary). While you can invoke member functions on an rvalue, you can only invoke const member functions. Also, everyone is right in saying that operator+ must alwasys return a new value.

Your operators should be implemented like this:

A operator+( const A& ) const;
A operator+( int m ) const;

However, binary operators which don't modify their left argument are probably better implemented as free functions:

class A { ... };

A operator+(const A& lhs, const A& rhs);
A operator+(const A& lhs, int rhs);

Usually, they are implemented on top of operator+=, which is implemented as a member:

class A {
  public:
   A& operator+=(const A& rhs);
   A& operator+=(int rhs);
};

inline A operator+(A lhs, const A& rhs) // note: lhs is passed by copy now
{
  lhs += rhs;
  return lhs;
}
A operator+(A lhs, int rhs) // note: lhs is passed by copy now
{
  lhs += rhs;
  return lhs;
}

Upvotes: 1

abir
abir

Reputation: 1797

As const A& operator+( const A& ) returns a const reference a non-const member function const A& operator+( int m ) can not be called over a const object. Either, the first operator should be defined as A& operator+( const A& ) or, the second operator as const A& operator+( int m )const; However, these changes will only make them technically correct, not aesthetically in majority of the cases, as a binary operator is not supposed to modify any of the input argument and yet to compute a result and return. Thus the result have to be returned by value or in case of C++0x , as a r-value reference. i.e A operator+(const A& rhs)const or A&& operator+(const A& rhs)const;

Upvotes: 1

R Samuel Klatchko
R Samuel Klatchko

Reputation: 76531

operator+ should return an instance, not a reference:

// as member function
A operator+(const A& other);

// as free function
A operator+(const A& left, const A& right);

To explain the specific problem is "returns a constant reference which is then passed to const A& operator+( int m )". Since you have a const reference, it cannot call that function because it's not a const method (i.e. const A& operator+( int m ) const).

That said, that is not the way to fix operator+. If you're returning a reference, what is it a reference to? A local in operator+ would be bad as you shouldn't return a reference to a local. A reference to a global would be bad because it will limit how your code can be used properly. A reference to allocated memory would be bad because it will leak memory. A reference to *this would be bad because then operator+ is acting like operator +=.

Upvotes: 6

JonM
JonM

Reputation: 840

The function needs to be const:

const A& operator+( int m ) const;

Upvotes: 1

Khaled Alshaya
Khaled Alshaya

Reputation: 96849

Because you are modifying the left-hand side object when adding. You can't do that with a const object. Take Samuel advice btw, because the idiomatic way is to return a new copy of the added objects.

Upvotes: 2

kennytm
kennytm

Reputation: 523214

which is then passed to "const A& operator+( int m )" if I'm not mistaken

No. Since the LHS is a const A& and RHS is an int, it will call*

[anyType] operator+ (int rhs) const
//                            ^^^^^ note the const here.

as you've only provided the non-const version const A& operator+( int m ), the compiler will complain.

*: Or operator+(const int& rhs) const or operator+(float rhs) const... The crucial point is that it must be a const method.

Upvotes: 7

Related Questions