Programming in C++

Operator Overloading

Gerald Senarclens de Grancy

Purpose of Operator Overloading

Use the built-in C++ operators on own types.

Allow using C++ operators on existing types that do not support them natively.

Related Conventions

C.168 (C: Classes and class hierarchies)
Define overloaded operators in the namespace of their operands

Using Pythonic Syntax in C++

Concatenate two lists in Python

l1 = [1, 2, 3, 4, 5, 6]  # or `list(range(1, 7))`
l2 = [1, 1, 1, 1, 1, 4]  # or `[1] * 5 + [4]`
l3 = l1 + l2
print(l3)

Without operator overloading, this syntax is not possible in C++.

Without operator overloading, the following does not work.

#include <iostream>
#include <vector>

int main(void) {
  std::vector<int> v1{1, 2, 3, 4, 5, 6};
  std::vector<int> v2(5, 1); v2.push_back(4);  // {1, 1, 1, 1, 1, 4}
  std::vector<int> v3 = v1 + v2;  // compiler problem
  std::cout << v3 << std::endl;  // compiler problem
}

Solution, Part 1: Overload the + Operator

using std::vector;
vector<int> operator+(const vector<int>& v1, const vector<int>& v2) {
  vector<int> v;
  v.insert(end(v), begin(v1), end(v1));
  v.insert(end(v), begin(v2), end(v2));
  return v;
}

Solution, Part 1: Overload the + Operator

Better to write generic code.

using std::vector;
template <class Type>
vector<Type> operator+(const vector<Type>& v1, const vector<Type>& v2) {
  vector<Type> v;
  v.insert(end(v), begin(v1), end(v1));
  v.insert(end(v), begin(v2), end(v2));
  return v;
}

Solution, Part 2: Overload the << Operator

template <class Type>
ostream& operator<<(ostream& out, const vector<Type>& v) {
  out << '[';
  for (const auto& e: v) {
    out << e << ", ";
  }
  out << "\b\b]"; // two backspace characters to overwrite final ", "
  return out;
}

Complete Solution

#include <iostream>
#include <vector>

using std::cout, std::endl;  // multiple using on same line is C++17
using std::vector;

namespace std {  // C.168: define overloaded operators in namespace of operands

template <class Type>
vector<Type> operator+(const vector<Type>& v1, const vector<Type>& v2) {
  vector<Type> v;
  v.insert(end(v), begin(v1), end(v1));
  v.insert(end(v), begin(v2), end(v2));
  return v;
}

template <class Type>
ostream& operator<<(ostream& out, const vector<Type>& v) {
  out << '[';
  for (const auto& e: v) {
    out << e << ", ";
  }
  out << "\b\b]"; // two backspace characters to overwrite final ", "
  return out;
}
}  // namespace std

int main(void) {
  vector<int> v1{1, 2, 3, 4, 5, 6};
  vector<int> v2(5, 1); v2.push_back(4);  // {1, 1, 1, 1, 1, 4}
  cout << v1 << endl;
  cout << v2 << endl;
  vector<int> v3 = v1 + v2;
  cout << v3 << endl;
}

operator_overloading.cpp

Questions
and feedback...