#include <iostream>
using namespace std;

template <typename T> //class T
class complex {
      T re, im;
public:
       complex(T _re, T _im) : re(_re), im(_im) {}
       complex(const complex & c) {re = c.re; im = c.im;}
       T Re() {return re;}
       T Im() {return im;}

template <typename U> friend ostream& operator<<(ostream&, const complex<U>&);
template <typename U> friend complex<U> operator+(const complex<U>&, const complex<U>&);
template <typename U> friend bool operator==(const complex<U>&, const complex<U>&);
};

template<typename T>
ostream& operator<<(ostream& os, const complex<T>& c) {
    os << c.re << " + " << c.im << " * i";
    return os;
}

template<typename T>
complex<T> operator+(const complex<T>& c1, const complex<T>& c2) {
    complex<T> r(c1);    r.re += c2.re;     r.im += c2.im; 
    return r;
}

template<typename T>
bool operator==(const complex<T>& c1, const complex<T>& c2) {
    if ( (c1.re != c2.re) || (c1.im != c2.im) ) return false;
    return true;
}

int main() {
    complex<int> a(2,3), b(5,7);
    complex<float> cf(2.2,3.3);
    cout << a << endl;
    cout << b << endl;
    cout << (a+b) << endl;
    cout << (a==b) << endl;
    cout << (a.Re()) << endl;
    cout << (a.Im()) << endl;
    cout << cf << endl;
    
    
}
