# operator << and conversion operator

C

#### cronusf

Suppose I have a class Complex and I overload operator double() to get
the real part. I also define:

std:stream& operator<<(std:stream& os, Complex& complex)
{
os << "(" << complex.real<< ", " << complex.imaginary << ")";

return os;
}

Now if I write:

Complex a(1.0, 2.0)
Complex b(1.0, 2.0)

cout << a + b << endl;

I have overloaded operator+ for Complex.
However, when I write this, it calls operator double() and outputs
that? Why? If I change to const Complex& it behaves as expected. If
I remove operator double() it behaves as expected and calls the

G

#### Garrett Hartshaw

Suppose I have a class Complex and I overload operator double() to get
the real part. I also define:

std:stream& operator<<(std:stream& os, Complex& complex)
{
os<< "("<< complex.real<< ", "<< complex.imaginary<< ")";

return os;
}

Now if I write:

Complex a(1.0, 2.0)
Complex b(1.0, 2.0)

cout<< a + b<< endl;

I have overloaded operator+ for Complex.
However, when I write this, it calls operator double() and outputs
that? Why? If I change to const Complex& it behaves as expected. If
I remove operator double() it behaves as expected and calls the

I would think that this would not work because the expression a + b is a
temporary and therefore cannot bind to a non-const reference. Therefore
your operator<< for Complex& is not considered, and the compiler
searches for another operator<<. However, I do not know why it would
consider the Complex overload when operator double is removed.
--Garrett

I

#### Ian Collins

Suppose I have a class Complex and I overload operator double() to get
the real part. I also define:

std:stream& operator<<(std:stream& os, Complex& complex)
{
os<< "("<< complex.real<< ", "<< complex.imaginary<< ")";

return os;
}

Now if I write:

Complex a(1.0, 2.0)
Complex b(1.0, 2.0)

cout<< a + b<< endl;

I have overloaded operator+ for Complex.
However, when I write this, it calls operator double() and outputs
that? Why? If I change to const Complex& it behaves as expected.

Probably because the result of a+b is a temporary and you can't bind a
temporary to a non-const reference.

C

#### cronusf

Probably because the result of a+b is a temporary and you can't bind a
temporary to a non-const reference.

That's what I thought at first, but If
I remove operator double() it behaves as expected and calls the

I

#### Ian Collins

That's what I thought at first, but If
I remove operator double() it behaves as expected and calls the

Well it shouldn't. You either have something else in your code you have
overlooked, or there's a bug in your compiler. Which compiler are you
using?

Y

#### Yakov Gerlovin

Interesting.
Just checked it on VC6/WinXp and on Solaris9/WS6 and the compilers
accepted both const and non-const versions of op<< for temp.

I

#### Ian Collins

Nobody cares what an old, broken compiler such as VC6 does. Use proper,
standards compliant C++ compilers.

Sun WS6 is also well past its use by date.

Ö

#### Öö Tiib

Given the operator precedence, your expression is evaluated as:

(cout << a) + (b << endl)

Not true by language parsing rules.
By standard it is evaluated like:

multiplicative-expression

shift-expression:

That results with:

((cout << (a + b)) << endl)

You probably mixed up precedence of << and % (that boost::format

C

#### cronusf

Probably because the result of a+b is a temporary and you can't bind a
Well it shouldn't.  You either have something else in your code you have
overlooked, or there's a bug in your compiler.  Which compiler are you
using?

I am using Visual Studio 2008. Here is a small compilable program
showing the issue:

#include <iostream>

class Complex
{
public:
Complex(float a, float b)
: real(a), imag(b)
{}

Complex operator+(const Complex& b)
{
return Complex(real+b.real, imag+b.imag);
}
/*
operator float()
{
return real;
}
*/
float real;
float imag;
};

std:stream& operator<<(std:stream& os, Complex& c)
{
os << "(" << c.real << ", " << c.imag << ")" << std::endl;

return os;
}

int main()
{
Complex c1(1.0f, 2.0f);
Complex c2(1.0f, 2.0f);

std::cout << c1 + c2 << std::endl;
}

Output: (2, 4)

If I uncomment the operator float(), and set a break point inside it,
it gets hit and the output is just 2 (the real part).

I

#### Ian Collins

I am using Visual Studio 2008. Here is a small compilable program
showing the issue:

#include<iostream>

class Complex
{
public:
Complex(float a, float b)
: real(a), imag(b)
{}

Complex operator+(const Complex& b)
{
return Complex(real+b.real, imag+b.imag);
}
/*
operator float()
{
return real;
}
*/
float real;
float imag;
};

std:stream& operator<<(std:stream& os, Complex& c)
{
os<< "("<< c.real<< ", "<< c.imag<< ")"<< std::endl;

return os;
}

int main()
{
Complex c1(1.0f, 2.0f);
Complex c2(1.0f, 2.0f);

std::cout<< c1 + c2<< std::endl;
}

Output: (2, 4)

That shouldn't compile. There isn't a suitable operator << for Complex.

I

#### Ian Collins

That shouldn't compile. There isn't a suitable operator << for Complex.

Which probably means that compiler doesn't enforce the can't bind a
temporary to a non const reference rule. So what you see is compiler,
rather than language specific.

A

#### Alf P. Steinbach /Usenet

* Ian Collins, on 28.10.2010 06:30:
Which probably means that compiler doesn't enforce the can't bind a temporary to
a non const reference rule. So what you see is compiler, rather than language
specific.

Yes, "cronusfh" is using Visual C++ 8.

Presumably he's ignoring the warning about non-standard language extension being
used.

Cheers,

- Alf

S

#### SG

Suppose I have a class Complex and I overload operator double()
to get the real part.

avoid "lossy" user-defined implicit conversions. Here, the resulting
double value won't properly represent the value of the original
complex object in general. Make the user explicitly say what he/she
intends to do to avoid any accidental data losses.

Cheers!
SG

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.