#include <iostream>
using namespace std;

class Rectangle
{
private:
    int width;
    int height;

public:
    Rectangle() : Rectangle(1, 1)
    {
    }

    Rectangle(int w, int h) : width(w), height(h)
    {
    }

    int getWidth()
    {
        return width;
    }

    int getHeight()
    {
        return height;
    }

    // binary - (as method): "this - rect2" (implicit first Rectangle)
    Rectangle operator-(Rectangle rect2)
    {
    	int newWidth = this->getWidth() - rect2.getWidth();
    	int newHeight = this->getHeight() - rect2.getHeight();

    	Rectangle result( newWidth, newHeight );
    	return result;
    }

    // unary - (as method): "-this" (implicit Rectangle), see below for implementation as standalone function
    Rectangle operator-()
    {
    	int newWidth = -this->width;
    	int newHeight = -this->height;

    	Rectangle result( newWidth, newHeight );
    	return result;
    }

    // scale a rectangle by factor (as method): "this * scale" (implicit Rectangle)
    Rectangle operator*( int scale )
    {
        int newWidth = this->getWidth() * scale;
        int newHeight = this->getHeight() * scale;

        Rectangle result( newWidth, newHeight );
        return result;
    }

    // update a rectangle by another (as method): "this += rect2" (implicit first Rectangle)
    Rectangle& operator+=(Rectangle rect2)
    {
        width = width + rect2.getWidth();
    	height = height + rect2.getHeight();

        return *this;
    }

    // update a rectangle by scaling it (as method): "this *= scale" (implicit Rectangle)
    Rectangle& operator*=( int scale )
    {
        this->width *= scale;
        this->height = this->height * scale;

        return *this;
    }
};


// binary + (as function): "rect1 + rect2" (both Rectangles given explicitly)
Rectangle operator+(Rectangle rect1, Rectangle rect2)
{
    int newWidth = rect1.getWidth() + rect2.getWidth();
    int newHeight = rect1.getHeight() + rect2.getHeight();

    Rectangle result( newWidth, newHeight );
    return result;
}

/*
// unary - implemented as standalone function (Rectangle given explicitly)
Rectangle operator-(Rectangle rect)
{
    int newWidth = -rect.getWidth();
    int newHeight = -rect.getHeight();

    Rectangle result( newWidth, newHeight );
    return result;
}
*/

// scale a rectangle by factor (as method): "scale * rect" (Rectangle given explicitly)
Rectangle operator*( int scale, Rectangle rect )
{
    // uses the other version "rect * scale" which was implemented as method
    return rect*scale;
}

void print(Rectangle rect)
{
    cout << rect.getWidth() << ", " << rect.getHeight() << endl;
}


int main()
{
    Rectangle r1( 10, 20 );
    Rectangle r2( 50, 30 );

    Rectangle r3 = r1 + r2;  // i.e. operator+(rect1, rect2), add(r1, r2)

    r3 = -r1;                // the unary -

    r3 = 2 * r1;             // scale * rect

    r3 = r1 * 2;             // rect * scale

    r3 *= 2;                 // double r3

    r1 += r2;                // enlarge r3

    r1 += r2 += r3;          // weird stuff

    r1 += r1 += r1;

    (r2 += r1) += r1;

    print(r2);

    r3 = r2 = r1 += r1 += r1;

    print(r1);
    print(r2);
    print(r3);

    return 0;
}