#include <iostream>
using namespace std;
template<typename T>
class Rectangle
{
private:
T width;
T height;
public:
Rectangle() : Rectangle(1, 1)
{
}
Rectangle(T w, T h) : width(w), height(h)
{
}
T getWidth() const
{
return width;
}
T getHeight() const
{
return height;
}
// binary - (as method): "this - rect2" (implicit first Rectangle)
Rectangle<T> operator-(const Rectangle<T>& rect2)
{
T newWidth = this->getWidth() - rect2.getWidth();
T newHeight = this->getHeight() - rect2.getHeight();
Rectangle<T> result( newWidth, newHeight );
return result;
}
// unary - (as method): "-this" (implicit Rectangle), see below for implementation as standalone function
Rectangle<T> operator-()
{
T newWidth = -this->width;
T newHeight = -this->height;
Rectangle<T> result( newWidth, newHeight );
return result;
}
// scale a rectangle by factor (as method): "this * scale" (implicit Rectangle)
Rectangle<T> operator*( T scale )
{
T newWidth = this->getWidth() * scale;
T newHeight = this->getHeight() * scale;
Rectangle<T> result( newWidth, newHeight );
return result;
}
// update a rectangle by another (as method): "this += rect2" (implicit first Rectangle)
Rectangle<T>& operator+=(const Rectangle<T>& rect2)
{
width = width + rect2.getWidth();
height = height + rect2.getHeight();
return *this;
}
// update a rectangle by scaling it (as method): "this *= scale" (implicit Rectangle)
Rectangle<T>& operator*=( int scale )
{
this->width *= scale;
this->height = this->height * scale;
return *this;
}
};
// binary + (as function): "rect1 + rect2" (both Rectangles given explicitly)
template<typename T>
Rectangle<T> operator+(const Rectangle<T>& rect1, const Rectangle<T>& rect2)
{
T newWidth = rect1.getWidth() + rect2.getWidth();
T newHeight = rect1.getHeight() + rect2.getHeight();
Rectangle<T> result( newWidth, newHeight );
return result;
}
/*
// unary - implemented as standalone function (Rectangle given explicitly)
template<typename T>
Rectangle<T> operator-(const Rectangle<T>& rect)
{
T newWidth = -rect.getWidth();
T newHeight = -rect.getHeight();
Rectangle<T> result( newWidth, newHeight );
return result;
}
*/
// scale a rectangle by factor (as method): "scale * rect" (Rectangle given explicitly)
template<typename T>
Rectangle<T> operator*( int scale, const Rectangle<T>& rect )
{
// uses the other version "rect * scale" which was implemented as method
return rect*scale;
}
template<typename T>
void print(const Rectangle<T>& rect)
{
cout << rect.getWidth() << ", " << rect.getHeight() << endl;
}
int main()
{
Rectangle<unsigned short> rect_ushort( 10, 20 );
Rectangle<long> rect_long( 50, 30 );
Rectangle<double> rect_double( 10, 20 );
Rectangle<int> r1( 10, 20 );
Rectangle<int> r2( 50, 30 );
Rectangle<int> 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;
r3 = r2 = r1 += r1 += r1;
print(r1);
print(r2);
print(r3);
return 0;
}