-x means (0-x) or means (-1*x)
because I want to overload operators,
which one is necessary to overload if i would like to make -x understanable for the compiler?

I have a user defined type: real
and I have operator overloading:
real operator+(real x1, real x2);
I also have constructor real(double)
and casting defined double() in my real class.

Now (double + real) or (real + double)
is understanable for the compiler?
If yes,
than the compiler makes double -> real first and add real + real
or makes real -> double first and add double + double?

If not, I have to make the following operator overloding also?:
real operator+(real x1, double x2);
real operator+(double x1, double x2);

>which one is necessary to overload if i would like to make -x understanable for the compiler?
The negation operator is a single argument member function:

class foo {
public:
  // Overload negation
  foo operator- ( const foo& obj );
};

>If yes,
>than the compiler makes double -> real first and add real + real
>or makes real -> double first and add double + double?

The function takes two reals, so as long as there's a conversion from double to real, the compiler will do it. Converting from real to double makes no sense because the compiler is matching actual types to expected types. The expected types are defined by the function parameter list.

>If not, I have to make the following operator overloding also?:
>real operator+(real x1, double x2);
>real operator+(double x1, double x2);

It's a good idea regardless. You'll find that performance reasons, libraries will often avoid implicit conversions like the one you have by overloading functions to match a number of different combinations.

Shouldn't OP's overloaded operators for + only take one parameter (and return real &)? (or am I missing something)

Edited 7 Years Ago by jonsca: n/a

>Shouldn't OP's overloaded operators for + only take one parameter
>(and return real &)? (or am I missing something)

Not all overloaded operators need to be member functions. The binary operators in particular are often better suited as non-member functions because it allows a certain flexibility in the ordering of the operands. For example, using member functions you're somewhat restricted:

class real {
public:
  real& operator+ ( const real& rhs );
  real& operator+ ( double rhs );
};

int main()
{
  real r;
  real s;

  r = r + 1.0;
  r = r + s;
  r = 1.0 + s; // Bzzt! Left operand must be a real object
}

But switching to non-member functions neatly fixes the problem:

#include <iostream>

class real {};

real operator+ ( const real& lhs, const real& rhs );
real operator+ ( const real& lhs, double rhs );
real operator+ ( double lhs, const real& rhs );

int main()
{
  real r;
  real s;

  // All okay
  r = r + 1.0;
  r = r + s;
  r = 1.0 + s;
}

>which one is necessary to overload if i would like to make -x understanable for the compiler?
The negation operator is a single argument member function:

class foo {
public:
  // Overload negation
  foo operator- ( const foo& obj );
};

That is not overloading the negation operator. Thats overloading
the subtraction operator. A negation has no arguments and
deals with the this pointer. If you want to do it that way, you will need to make that
function a friend function.

Edited 7 Years Ago by firstPerson: n/a

>If you want to do it that way, you will need to make that function a friend function.
Yes, thank you for the correction. I'll blame a disconnect between my brain thinking friend and my fingers thinking member. ;)

>If you want to do it that way, you will need to make that function a friend function.
Yes, thank you for the correction. I'll blame a disconnect between my brain thinking friend and my fingers thinking member. ;)

No problem. Its good to see that you are a human as well
and not an all knowing android.

>Its good to see that you are a human as well
You should see me typing boilerplate code: itn doh! ^H^H int amin what the?! ^H^H^H^H int mina crap! ^H^H^H int main) *sigh* ^H int main(itn *sob!*

*stalks off to watch TV*

Edited 7 Years Ago by Narue: n/a

Is there any reason dear Narue that you write

real operator+ ( const real& lhs, const real& rhs );
real operator+ ( const real& lhs, double rhs );
real operator+ ( double lhs, const real& rhs );

And not "const double&" like this?

real operator+ ( const real& lhs, const real& rhs );
real operator+ ( const real& lhs, const double& rhs );
real operator+ ( const double& lhs, const real& rhs );

Is there any reason dear Narue that you write

real operator+ ( const real& lhs, const real& rhs );
real operator+ ( const real& lhs, double rhs );
real operator+ ( double lhs, const real& rhs );

And not "const double&" like this?

real operator+ ( const real& lhs, const real& rhs );
real operator+ ( const real& lhs, const double& rhs );
real operator+ ( const double& lhs, const real& rhs );

Because if it was const double& then you can't just say
realObject + 5, because 5 is a literal and we can't have a refrence to it. Instead you would have to create a variable, and do :

double dummy = 5.0;
realObject + dummy;

>Because if it was const double& then you can't just say
>realObject + 5, because 5 is a literal and we can't have a refrence to it.

Fortunately, binding an rvalue to a const reference is legal. I simply default to passing built-in types by value as a matter of habit. ;)

Edited 7 Years Ago by Narue: n/a

>Because if it was const double& then you can't just say
>realObject + 5, because 5 is a literal and we can't have a refrence to it.

Fortunately, binding an rvalue to a const reference is legal. I simply default to passing built-in types by value as a matter of habit. ;)

Ok, you proved me wrong.

>What does it mean "rvalue" ?
The details are kind of murky now, but originally lvalue meant anything that could be on the left hand side of an assignment expression, and rvalue meant anything that could be on the right hand side:

<lvalue> = <rvalue>;

That's not the whole story, of course. One exception brings you to modifiable and non-modifiable lvalues. A non-modifiable lvalue is an lvalue but can't be assigned to (const objects, for example). Further, lvalues can be used as rvalues and thus become rvalues in the expression. Sometimes you hear about lvalues being objects with an address, but then you get into register variables and cases where rvalue expressions can refer to objects.

The basic definition ( <lvalue> = <rvalue> ) is generally sufficient though. :)

Not all overloaded operators need to be member functions. The binary operators in particular are often better suited as non-member functions because it allows a certain flexibility in the ordering of the operands.

Thank you for the explanation, Narue! :)

This article has been dead for over six months. Start a new discussion instead.