a.x1a.y21Vec2 a{1, 2}, b{3, 4};2Vec2 c = a + b;3a += b;4if (a == c)5 std::cout << c;b.x3b.y4the compiler callsc.xc.ya == cprints13424634464466true46(4, 6)
Violet card: the code; a line glows while it runsKhaki blocks: Vec2 objects; rose block: the operator function being calledTokens: values passed into the function (khaki) and the result it returns (rose)On the left: five lines of C++. On the right: the Vec2 objects a and b at the back, the operator function the compiler calls in the middle, and in front the result c, the bool a == c and the console. Each operator is a function call: the operands' values travel into the function and its result travels out. a + b builds a new c, a += b changes a itself, a == c compares member by member, and std::cout << c prints. The card's five lines are the body of main in a complete program that defines Vec2 and its four operators. It compiles without warnings with g++ -std=c++20 -Wall -Wextra and prints (4, 6).

The idea

  1. Line 1 makes two Vec2 objects, a and b, each holding an x and a y. For int, the + sign already means add. For a class you write yourself, a + b means nothing until you give it a meaning.

Writing operators

More operators

What happens

;; step 1/8 · objects
struct Vec2 { int x, y; };
1  Vec2 a{1, 2}, b{3, 4};
a  { x: 1, y: 2 }
b  { x: 3, y: 4 }
without operator+:  a + b  →  compile error
  g++: no match for 'operator+' (operand types are 'Vec2' and 'Vec2')

For an expression a @ b where an operand has class or enumeration type, the compiler looks for both a member a.operator@(b) and a free operator@(a, b), and overload resolution picks the best match. Defaulted comparisons (= default) and the rewriting of a != b into !(a == b) are both new in C++20. Before C++20 you wrote operator== and operator!= by hand.