Devashish Jaiswal
Devashish Jaiswal

Reputation: 11

Overloading I/O streams operator and pre/post-increment/decrement operators error?

Here is a code I found in website from which I am learning C++. I don't know how to debug a program, so I can't figure out what's the problem with.

#include <iostream>

using namespace std;
class Complex
{
int real;
int img;
public:
Complex()
{
    real = 0;
    img = 0;
}

Complex(int r, int i)
{
    real = r;
    img = i;
}

Complex& operator++();
Complex operator++(int);

friend Complex operator+(Complex &a, Complex &b);
friend ostream& operator<<(ostream &out, Complex &a);
friend istream& operator>>(istream &in, Complex &a);

void display()
{
    using namespace std;
    cout << real << " + " << img << endl;
}

};

Complex& Complex::operator++()
{
    ++real;
    ++img;
    return *this;
}

Complex Complex::operator++(int)
{
    Complex temp(*this);
    ++(*this);
    return temp;
}

Complex operator+(Complex &a, Complex &b)
{
    int x = a.real + b.real;
    int y = a.img + b.img;
    return Complex(x, y);
}
ostream& operator<<(ostream &out, Complex &a)
{
    using namespace std;
    out << a.real << " + " << a.img << endl;
    return out;
}

istream& operator>>(istream &in, Complex &a)
{
    using namespace std;
    cout << "Enter the real part" << endl;
    in >> a.real;
    cout << "Enter the imaginary part" << endl;
    in >> a.img;
    return in;
}

int main()
{
    Complex a;
    cin >> a;
    Complex b(11,8);
    cout << "a is :" << a << endl;
    cout << "b is :" << b << endl;
    Complex c = Complex(a + b);
    cout << "c is :" << c << endl;
    cout << c;
    cout << c++;
    cout << c;
    cout << ++c;
    cout << c;
}

The compiler gives error from the line where I attempt to increment an instance of Complex inside main(). As far as I can see, everything is quite right, but Code::Blocks gives these errors:

  1. error: cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&'|

  2. error: initializing argument 1 of 'std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = Complex]|

Now this made me believing that (overloaded) I/O operators has some special rules that should be followed in order to use with (overloaded) increment/decrement operators.

Questions:

  1. Is that true, or something is wrong in the code that I am not catching? I am a beginner to this field.

  2. Does overloading output/input operator and increment(post,pre)/decrement operators have some extra rules to use them together?

P.S.: Forgive me for my bad English...Thanks

Upvotes: 1

Views: 191

Answers (3)

user5241471
user5241471

Reputation: 105

Make the parameter "Complex &a" a const (e.g. const Complex &a) in the output operator overloading function.

Upvotes: 0

Some programmer dude
Some programmer dude

Reputation: 409404

The problem is the use of a non-const referense in the output operator function. The problem with this is that when you use the postfix increment operator (c++) then the operator++ function returns a new Complex object by value, and this object is temporary, and you can't bind a non-const reference to a temporary object.

Simple fix: Change the argument to be a const reference:

ostream& operator<<(ostream &out, const Complex &a) { ... }

Upvotes: 1

TartanLlama
TartanLlama

Reputation: 65720

I don't get the same errors as you, but these are certainly an issue:

ostream& operator<<(ostream &out, Complex &a);
Complex operator++(int);
cout << c++;

You have declared operator<< to take its Complex argument by reference-to-non-const, then you try and bind a temporary to that reference. Temporaries cannot bind to non-const references.

The simple fix for this is to declare your operator to take a by reference-to-const so that rvalues can bind to it:

ostream& operator<<(ostream &out, const Complex &a);

Upvotes: 1

Related Questions