## Operators to overload

- Assignment operator
- Bitwise shift operators
- Function call operator
- Comparison operators
- Arithmetic operators
- Array subscripting operators
- Pointer operators

## Assignment operator

You only need to implement the assignment operator if you need to implement the copy constructor and destructor – and vice-versa.

Use the *copy-and-swap idiom* to implement the assignment operator:

- Take
`other`

by value – this invokes the copy constructor - Swap the contents of
`this`

with`other`

– you need to implement`swap`

`other`

is destroyed at the end of the function, taking the old state with it

X& X::operator=(X other) { swap(other); return *this; }

Note that this does not do a self-assignment check, but self-assignment is guaranteed to be harmless.

## Bitwise shift operators

These are most commonly overloaded to insert into and extract from iostreams, or some other sort of stream.

They need to be friend functions if they need to access private members, as they can’t be members themselves.

When used with iostreams, these functions need to take the stream by non-const reference (iostreams cannot be copied and will be modified) and return it by reference.

std::ostream& operator<<(std::ostream& os, const T& obj) { // Write the object to the stream return os; } std::istream& operator>>(std::istream& is, T& obj) { // Read the object from the stream return is; }

## Function call operator

Use the function all operator to make a functor.

This is always a member function.

It can be overloaded to take any number and type of arguments.

It can return any type, or `void`

.

Functors are often copied, so the class must be copyable and inexpensive to copy.

## Comparison operators

These should be implemented as non-member functions.

Missing operators are not automatically deduced from the others.

The standard library only uses < (*strict weak ordering*), but you should overload them all for consistency.

You only need to fully implement `operator==`

and `operator<`

, as the others can be implemented in terms of them. They also make your class model the `EqualityComparable`

and `LessThanComparable`

concepts.

bool operator ==(const X& lhs, const X& rhs) { // Do actual comparison } bool operator < (const X& lhs, const X& rhs) { // Do actual comparison } bool operator !=(const X& lhs, const X& rhs) { return !operator==(lhs, rhs); } bool operator > (const X& lhs, const X& rhs) { return operator< (rhs, lhs); } bool operator <=(const X& lhs, const X& rhs) { return !operator> (lhs, rhs); } bool operator >=(const X& lhs, const X& rhs) { return !operator< (lhs, rhs); }

## Arithmetic operators

### Unary arithmetic operators

If you overload the prefix form, you should also overload the postfix form, and vice-versa.

class X { X& operator++() { // Do actual increment return *this; }

The postfix form is distinguished by a dummy `int`

argument.

You need to use a temporary to save the old value before incrementing it so that the old value can be returned.

X operator++(int) { X temp(*this); operator++(); return temp; } };

### Binary arithmetic operators

You should overload `op`

and `op=`

.

`op=`

is a member while `op`

is a non-member.

You can implement `op`

in terms of `op=`

.

`op`

needs to take its lhs by copy so it can modify and return it without modifying the original.

class X { X& operator+=(const X& rhs) { // Do actual addition of rhs to *this return *this; } }; X operator+(X lhs, const X& rhs) { lhs += rhs; return lhs; }

## Array subscripting operators

These must be members. They can only take 1 argument (although it can be of any type).

You should implement `const`

and non-`const`

versions to allow const overloading.

class X { value_type& operator[](size_type index); const value_type& operator[](size_type index) const; };

## Pointer operators

This is how you implement a smart pointer.

Overload the `->`

and `*`

operators.

You should implement `const`

and `non-const`

versions to allow const overloading.

class SmartPtr { value_type& operator*(); const value_type& operator*() const; value_type* operator->(); const value_type* operator->() const; };