operator << and conversion operator

Discussion in 'C++' started by cronusf, Oct 27, 2010.

  1. cronusf

    cronusf Guest

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

    std::eek:stream& operator<<(std::eek: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
    Complex overload of operator <<.
     
    cronusf, Oct 27, 2010
    #1
    1. Advertising

  2. On 10/26/2010 09:36 PM, cronusf wrote:
    > Suppose I have a class Complex and I overload operator double() to get
    > the real part. I also define:
    >
    > std::eek:stream& operator<<(std::eek: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
    > Complex overload of operator<<.


    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
     
    Garrett Hartshaw, Oct 27, 2010
    #2
    1. Advertising

  3. cronusf

    Ian Collins Guest

    On 10/27/10 02:36 PM, cronusf wrote:
    > Suppose I have a class Complex and I overload operator double() to get
    > the real part. I also define:
    >
    > std::eek:stream& operator<<(std::eek: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.

    --
    Ian Collins
     
    Ian Collins, Oct 27, 2010
    #3
  4. cronusf

    cronusf Guest

    On Oct 26, 7:11 pm, Ian Collins <> wrote:
    > On 10/27/10 02:36 PM, cronusf wrote:
    >
    >
    >
    > > Suppose I have a class Complex and I overload operator double() to get
    > > the real part.  I also define:

    >
    > > std::eek:stream&  operator<<(std::eek: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.


    That's what I thought at first, but If
    I remove operator double() it behaves as expected and calls the
    Complex overload of operator <<.
     
    cronusf, Oct 27, 2010
    #4
  5. cronusf

    Ian Collins Guest

    On 10/27/10 05:34 PM, cronusf wrote:
    > On Oct 26, 7:11 pm, Ian Collins<> wrote:
    >> On 10/27/10 02:36 PM, cronusf wrote:
    >>
    >>
    >>
    >>> Suppose I have a class Complex and I overload operator double() to get
    >>> the real part. I also define:

    >>
    >>> std::eek:stream& operator<<(std::eek: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.

    >
    > That's what I thought at first, but If
    > I remove operator double() it behaves as expected and calls the
    > Complex overload of operator<<.


    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?

    --
    Ian Collins
     
    Ian Collins, Oct 27, 2010
    #5
  6. 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.
     
    Yakov Gerlovin, Oct 27, 2010
    #6
  7. cronusf

    Ian Collins Guest

    On 10/27/10 11:38 PM, Leigh Johnston wrote:
    > On 27/10/2010 11:36, Yakov Gerlovin wrote:
    >> 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.

    >
    > 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.

    --
    Ian Collins
     
    Ian Collins, Oct 28, 2010
    #7
  8. cronusf

    Öö Tiib Guest

    On 27 okt, 15:01, "Daniel T." <> wrote:
    > In article
    > <>,
    >
    >
    >
    >  cronusf <> wrote:
    > > Suppose I have a class Complex and I overload operator double() to get
    > > the real part.  I also define:

    >
    > > std::eek:stream& operator<<(std::eek: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
    > > Complex overload of operator <<.

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

    additive-expression:
    multiplicative-expression
    additive-expression + multiplicative-expression
    additive-expression - multiplicative-expression

    shift-expression:
    additive-expression
    shift-expression << additive-expression
    shift-expression >> additive-expression

    That results with:

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

    You probably mixed up precedence of << and % (that boost::format
    overloads as separator).
     
    Öö Tiib, Oct 28, 2010
    #8
  9. cronusf

    cronusf Guest

    > >> 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
    > > Complex overload of operator<<.

    >
    > 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::eek:stream& operator<<(std::eek: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).
     
    cronusf, Oct 28, 2010
    #9
  10. cronusf

    Ian Collins Guest

    On 10/28/10 05:10 PM, cronusf wrote:
    >>>> 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
    >>> Complex overload of operator<<.

    >>
    >> 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::eek:stream& operator<<(std::eek: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.

    --
    Ian Collins
     
    Ian Collins, Oct 28, 2010
    #10
  11. cronusf

    Ian Collins Guest

    On 10/28/10 05:18 PM, Ian Collins wrote:
    > On 10/28/10 05:10 PM, cronusf wrote:
    >>
    >> std::eek:stream& operator<<(std::eek: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.


    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.

    --
    Ian Collins
     
    Ian Collins, Oct 28, 2010
    #11
  12. * Ian Collins, on 28.10.2010 06:30:
    > On 10/28/10 05:18 PM, Ian Collins wrote:
    >> On 10/28/10 05:10 PM, cronusf wrote:
    >>>
    >>> std::eek:stream& operator<<(std::eek: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.

    >
    > 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

    --
    blog at <url: http://alfps.wordpress.com>
     
    Alf P. Steinbach /Usenet, Oct 28, 2010
    #12
  13. cronusf

    SG Guest

    On 27 Okt., 03:36, cronusf wrote:
    > Suppose I have a class Complex and I overload operator double()
    > to get the real part.


    I would consider this a /misuse/ of operator overloading. Try to
    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
     
    SG, Oct 28, 2010
    #13
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Master of C++
    Replies:
    4
    Views:
    719
    Karl Heinz Buchegger
    Feb 7, 2005
  2. Replies:
    0
    Views:
    379
  3. Arvid Requate
    Replies:
    2
    Views:
    992
    Alf P. Steinbach
    Jun 23, 2006
  4. hurcan solter
    Replies:
    3
    Views:
    733
    Cholo Lennon
    Aug 29, 2007
  5. , India
    Replies:
    2
    Views:
    478
    Fraser Ross
    Sep 15, 2009
Loading...

Share This Page