In my comments, I suggested two alternative solutions but while fiddling around with the sample code I even found a third one.
The sample code:
#include <iostream>
// Version 1: (return type fixed)
class Complex1 {
friend std::ostream& operator << (std::ostream &out, const Complex1 &c);
private:
int a;
public:
explicit Complex1(int a): a(a) { }
// operator + as member
Complex1 operator + (const Complex1 &c) const
{
return Complex1(a + c.a);
}
};
std::ostream& operator << (std::ostream &out, const Complex1 &c)
{
return out << c.a;
}
// Version 2: (two overloaded operators)
class Complex2 {
friend std::ostream& operator << (std::ostream &out, const Complex2 &c);
friend int operator+(const Complex2 &c, const Complex2 &d);
friend int operator+(int c, const Complex2 &d);
private:
int a;
public:
explicit Complex2(int a): a(a) { }
};
std::ostream& operator << (std::ostream &out, const Complex2 &c)
{
return out << c.a;
}
int operator+(const Complex2 &c, const Complex2 &d)
{
return c.a + d.a;
}
int operator+(int c, const Complex2 &d)
{
return c + d.a;
}
// Version 3: (implicit conversion with constructor)
class Complex3 {
friend std::ostream& operator << (std::ostream &out, const Complex3 &c);
private:
int a;
public:
Complex3(int a): a(a) { }
// operator + as member
int operator+(const Complex3 &c) const
{
return a + c.a;
}
};
std::ostream& operator << (std::ostream &out, const Complex3 &c)
{
return out << c.a;
}
// Check everything out:
using namespace std;
int main()
{
cout << "Version 1:" << endl;
{ Complex1 c1(3), c2(5), c3(2);
Complex1 c4 = c1 + c2 + c3;
cout << "c4: " << c4 << endl;
}
cout << "Version 2:" << endl;
{ Complex2 c1(3), c2(5), c3(2);
Complex2 c4 = Complex2(c1 + c2 + c3);
cout << "c4: " << c4 << endl;
}
cout << "Version 3:" << endl;
{ Complex1 c1(3), c2(5), c3(2);
Complex1 c4 = c1 + c2 + c3;
cout << "c4: " << c4 << endl;
}
cout << "done." << endl;
return 0;
}
You may compile and run the code on ideone.
Complex1
provides a fixed operator as member
Complex1 Complex1::operator + (const Complex1 &c) const;
Hence, (c1 + c2) + c3 is
(Complex1 × Complex1 → Complex1) × Complex1 → Complex1
Complex2
provides two overloaded operators as non-members
int operator+(const Complex2 &c, const Complex2 &d);
int operator+(int c, const Complex2 &d);
Hence, c1 + c2 is
Complex2 × Complex2 → int
and (c1 + c2) + c3 is
int × Complex2 → int
Complex3
is very similar like the original sample with the essential difference that I provided a non-explicit
constructor which accepts an int
. This means the compiler will use it as conversion operator when necessary.
(With a proper constructor, the operator issue probably hadn't been noticed soon.)
Thus, c1 + c2 is
Complex3 × Complex3 → int
and (c1 + c2) + c3 is
(int → Complex3) × Complex3 → int