AI InterviewSearch…Search problems, topics, or pages…Ctrl KGet started
Skip to content

11 Operator overloading / Checkpoint

Checkpoint — Operator overloading

25 min · +25 XP · 3 exercises · 14 questions

Exercises0/3
Quiz · 70% to clear14 q

This checkpoint covers the whole module: which operators to overload and where, the compound-first idiom, == and the defaulted <=> with its ordering categories, << and >> as free functions that respect the stream's state, operator[] pairs, function objects as comparators and hashes, and explicit on constructors and conversions.

How it works. Thirteen questions and three programs. You need 70% on the questions and every program accepted to clear the module. You can retake it as often as you like; your best score counts.

Before you start, make sure you can answer these from memory:

  • Why must 2 * v be a free function rather than a member of Vec2?
  • What does a defaulted operator<=> give you that a hand-written one does not?
  • Which ordering category does a struct with a double member deduce, and why?
  • Why does std::setw(10) << money need operator<< to insert one string?
  • What goes wrong when a comparator's operator() is not const?
  • Which contexts accept an explicit operator bool, and which refuse it?

The three programs are a Polynomial with arithmetic, evaluation through operator() and a formatted <<; a grid walk that counts visits through a std::hash<Point> specialisation and prints the cells sorted; and a Duration ledger that reads h:mm:ss through >>, orders with a defaulted <=> and prints through << without leaking a fill character.

Common questions

Why must 2 * v be a free function rather than a member of Vec2?

A member operator's left operand must already be the class type and never receives an implicit conversion, so a member Vec2::operator*(double) handles v * 2 but not 2 * v. A free function operator*(double, Vec2) treats both operands as ordinary parameters.

Which ordering category does a struct with a double member deduce?

std::partial_ordering. A defaulted auto operator<=> deduces the weakest category among its members, and double is only partially ordered because a NaN is neither less than, equal to nor greater than anything. Declare the return type as std::strong_ordering to turn that into a compile error instead.

Which contexts accept an explicit operator bool?

Only contextual conversions: the conditions of if, while and for, the first operand of ?:, the operands of !, && and ||, and an explicit static_cast<bool>. Initialising a bool or an int from the object, or using it in arithmetic, is refused.

What goes wrong when a comparator's operator() is not const?

std::set and std::map call the comparator through a const object, so a non-const operator() cannot be called there; libstdc++ stops compilation with a static assertion that the comparison object must be invocable as const. Mark every comparator's call operator const.

C++ Operator Overloading Quiz: Spaceship, Streams, Functors

Practise C++ operator overloading with 13 questions and three programs on the compound-first idiom, spaceship operator, stream operators, hashing and explicit.

  • Course: C++ study plan
  • Module: Operator overloading
  • Kind: Checkpoint — cleared at 70%
  • Reading time: 25 min
  • Runtime: Clang 18 · C++20

Checkpoint — Operator overloading is the checkpoint that closes the Operator overloading module: a graded quiz and whole-program exercises, passed at 70%.

Instructions

This checkpoint covers the whole module: which operators to overload and where, the compound-first idiom, == and the defaulted <=> with its ordering categories, << and >> as free functions that respect the stream's state, operator[] pairs, function objects as comparators and hashes, and explicit on constructors and conversions.

How it works. Thirteen questions and three programs. You need 70% on the questions and every program accepted to clear the module. You can retake it as often as you like; your best score counts.

Before you start, make sure you can answer these from memory:

  • Why must 2 * v be a free function rather than a member of Vec2?
  • What does a defaulted operator<=> give you that a hand-written one does not?
  • Which ordering category does a struct with a double member deduce, and why?
  • Why does std::setw(10) << money need operator<< to insert one string?
  • What goes wrong when a comparator's operator() is not const?
  • Which contexts accept an explicit operator bool, and which refuse it?

The three programs are a Polynomial with arithmetic, evaluation through operator() and a formatted <<; a grid walk that counts visits through a std::hash<Point> specialisation and prints the cells sorted; and a Duration ledger that reads h:mm:ss through >>, orders with a defaulted <=> and prints through << without leaking a fill character.

Common questions

Why must 2 * v be a free function rather than a member of Vec2?

A member operator's left operand must already be the class type and never receives an implicit conversion, so a member Vec2::operator*(double) handles v * 2 but not 2 * v. A free function operator*(double, Vec2) treats both operands as ordinary parameters.

Which ordering category does a struct with a double member deduce?

std::partial_ordering. A defaulted auto operator<=> deduces the weakest category among its members, and double is only partially ordered because a NaN is neither less than, equal to nor greater than anything. Declare the return type as std::strong_ordering to turn that into a compile error instead.

Which contexts accept an explicit operator bool?

Only contextual conversions: the conditions of if, while and for, the first operand of ?:, the operands of !, && and ||, and an explicit static_cast<bool>. Initialising a bool or an int from the object, or using it in arithmetic, is refused.

What goes wrong when a comparator's operator() is not const?

std::set and std::map call the comparator through a const object, so a non-const operator() cannot be called there; libstdc++ stops compilation with a static assertion that the comparison object must be invocable as const. Mark every comparator's call operator const.

Exercises

Polynomial arithmetic

Write a Polynomial class over long long coefficients (stored lowest degree first, trailing zeros trimmed so the zero polynomial is empty) with += and *= as members, + and * derived from them, operator()(x) that evaluates the polynomial at an integer x, and an operator<< that prints it in the usual form: highest degree first, zero terms skipped, a coefficient of 1 omitted except in the constant term, x for degree 1 and x^k above, terms joined by + or - , and a lone 0 for the zero polynomial. Examples: 3x^2 + 2x + 1, x - 1, -x^3 - 2x^2 - x, 0.

Input: two polynomials, each on a line as d c0 c1 … cd (degree, then the coefficients of x^0 to x^d), then a line with an integer x. Output: seven lines: p = …, q = …, p + q = …, p * q = …, p(x) = …, q(x) = …, (p * q)(x) = …, with the actual value of x in the parentheses.

2 1 2 3
1 -1 1
5

prints

p = 3x^2 + 2x + 1
q = x - 1
p + q = 3x^2 + 3x
p * q = 3x^3 - x^2 - x - 1
p(5) = 86
q(5) = 4
(p * q)(5) = 344

Grid visits with a hashed key

A walker starts at (0, 0) on an integer grid and follows a string of moves: U (y + 1), D (y − 1), L (x − 1), R (x + 1); any other character is ignored. Count how many times each cell is visited — the start counts as one visit — in a std::unordered_map<Point, int>. That needs a Point struct with a defaulted operator<=> (which also provides the == the map requires and the < you will sort by) and a specialisation template <> struct std::hash<Point> that combines the two member hashes. Never print in the map's own order: copy the cells that were visited more than once into a std::vector and sort it.

Input: one line, the move string (possibly empty). Output: distinct=<number of different cells visited>, revisited=<number of cells visited more than once>, then those cells in ascending (x, y) order as (x, y): <visits>.

UDUD

prints

distinct=2
revisited=2
(0, 0): 3
(0, 1): 2

A duration ledger

Write a Duration class holding a number of seconds with: an operator>> that reads the form h:mm:ss (hours with one to nine digits, then exactly two digits each for minutes and seconds, both 00–59) and sets failbit on anything else; an operator<< that prints the same form with minutes and seconds zero-padded — and restores the stream's fill character afterwards; += and +; and a defaulted operator<=> so the durations can be sorted with std::sort.

Input: n (at least 1), then n durations, one per line. Output: total <sum>, longest <max>, shortest <min>, the n durations in ascending order one per line, then count followed by n printed with std::setw(4) — which comes out right only if your << put the fill character back. If a duration is malformed, print bad duration and nothing else.

3
1:30:00
0:45:30
2:00:15

prints

total 4:15:45
longest 2:00:15
shortest 0:45:30
0:45:30
1:30:00
2:00:15
count   3

In this module: Operator overloading

← Conversion operators and explicit · Function templates — one definition, every type →