You can overload all basic arithmetic operators:

Overloading for all operators is the same. Scroll down for explanation

Overloading outside of class/struct:

//operator+ should be implemented in terms of operator+=
T operator+(T lhs, const T& rhs)
{
    lhs += rhs;
    return lhs;
}

T& operator+=(T& lhs, const T& rhs)
{
    //Perform addition
    return lhs;
}

Overloading inside of class/struct:

//operator+ should be implemented in terms of operator+=
T operator+(const T& rhs)
{
    *this += rhs;
    return *this;
}

T& operator+=(const T& rhs)
{
    //Perform addition
    return *this;
}

Note: operator+ should return by non-const value, as returning a reference wouldn’t make sense (it returns a new object) nor would returning a const value (you should generally not return by const). The first argument is passed by value, why? Because

  1. You can’t modify the original object (Object foobar = foo + bar; shouldn’t modify foo after all, it wouldn’t make sense)
  2. You can’t make it const, because you will have to be able to modify the object (because operator+ is implemented in terms of operator+=, which modifies the object)

Passing by const& would be an option, but then you will have to make a temporary copy of the passed object. By passing by value, the compiler does it for you.