Reputation: 9056
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
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
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
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
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
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