Module 5 — Exercises¶
Every exercise states its level, its task, and the observable result that counts as success. If you cannot tell whether you succeeded without reading a solution, the exercise is defective — tell the course maintainers.
Solutions are referenced at the end of the page, mostly to programs you have already been given. Attempt each exercise before looking.
Warm-up [L1 Understand]¶
W1 — operator classification¶
Task. For each of these, say whether it must be a member, may be either, and what the left operand is:
=, [], (), ->, + (two of your own type), << (output), == (two of
your own type), == (your type and a std::string), operator bool, &&,
[] on a const object.
Success looks like. Ten verdicts, each with the left operand named, and two of them marked "must not be overloaded at all" with a reason.
Stuck? Concepts §3 and §11.
W2 — which function runs?¶
Task. Six lines of code containing =. For each, say whether it calls the copy
constructor, the copy assignment operator, or neither.
Book a(1, "C++ Primer");
Book b = a; // 1
Book c(a); // 2
Book d = Book(3, "STL"); // 3
d = a; // 4
Book e = std::move(a); // 5
c = c; // 6
Success looks like. Six answers, and a one-word rule that decided all of them.
Stuck? Concepts §7.
W3 — read the error message¶
Task. Each message below is one line shorter than it should be. Say what is missing and what to write.
error: 'operator<<' must take exactly one argument
error: 'Book& operator=(Book&, const Book&)' must be a non-static member function
error: no match for 'operator!=' (operand types are 'Book' and 'Book')
error: invalid use of member 'Book::id_' in static member function
Success looks like. Four fixes, and for the last one, a sentence saying what
this has to do with it.
Stuck? Misconceptions, Part 2.
W4 — the three meanings of static¶
Task. Three declarations, three meanings:
static int counter; // inside a class
static int tally = 0; // inside a function
static void helper(); // at file scope
Success looks like. One sentence each: what it belongs to, when it is created, and when it is destroyed.
Stuck? Concepts §8–10.
Core [L2 Apply] · [L3 Modify] · [L4 Analyze]¶
C1 — make a type printable, comparable and sortable [L2 Apply]¶
Task. Take the Book type from Module 4's Lab 4 solution — private id_ and
title_, honest interface, no setters — and add the four operators it needs:
==, <, !=, <<. Then sort a vector of ten books by identifier, print them,
and find one with std::find.
Success looks like.
std::sortcompiles and produces identifier order, with two duplicate identifiers present and both retained;std::findfinds a book you name by identifier, and returnsend()for one you do not;std::cout << bookproduces one readable line, and the whole catalogue prints in a loop;- the file builds with
g++ -std=c++17 -Wall -Wextraand no warnings.
Note. std::find uses ==, std::sort uses <. If they disagree about
identity, one of the two results is wrong — that is the point of the exercise.
C2 — fix a type whose two orders disagree [L3 Modify] (this one is deliberately broken)¶
Task. This type compiles, sorts and searches — and its results disagree:
class Book {
public:
bool operator==(const Book& other) const { return id_ == other.id_; }
bool operator<(const Book& other) const {
return title_ < other.title_; // a different notion of identity
}
private:
int id_;
std::string title_;
};
Make a sorted vector and a std::find return results that are consistent with each
other. Then write three sentences: what was inconsistent, which of the two you kept
as the identity, and what a caller must do to order by the other.
Success looks like. A program in which "the elements are sorted" and "std::find
finds the element" cannot contradict each other, plus the three sentences.
Stuck? Debugging, Failure B.
C3 — two fixes for a link error, and a reason to prefer one [L3 Modify]¶
Task. Cause this failure, then fix it twice:
Fix (a): inline static. Fix (b): a definition in the .cpp. Then write one
sentence on when each is preferable.
Success looks like. Both versions build and run; the sentence names the C++17 rule and what (b) costs in a multi-file project.
C4 — an invalid comparator, and what the standard says about it [L4 Analyze]¶
Task. Write operator< using <=, sort a vector containing duplicates, and
record what happens: the order, whether it is stable across runs, and whether
anything warned you. Then fix it and record the difference.
Success looks like. A paragraph naming the violated property (irreflexivity), the standard's term for the consequence (undefined behaviour), and an explicit statement of what you observed on this machine — with the caveat that a wrong order is one possible outcome of undefined behaviour, not a guarantee.
Note. This recorded observation is a Lab 5 deliverable, so keep it.
Challenge [L4 Analyze] · [L5 Design]¶
X1 — explain why a static member function cannot be const [L4 Analyze]¶
Task. Write the explanation, in terms of this, and give it a checkable
consequence: something a reader can test to see that the rule is not arbitrary.
Success looks like. An explanation of the form "const qualifies X; X does not
exist here; therefore the question has no answer rather than a difficult one", plus
a consequence such as "every function that is static cannot be a const member,
so a factory function has no const-ness to offer, and a caller cannot express
'this class operation does not modify anything'" — or a better consequence than
that.
How you will be judged. Whether the consequence is testable. "It feels wrong" scores nothing.
X2 — decide member versus free, eight times, with reasons [L5 Design]¶
Task. For the running catalogue system, decide for each of these whether it is a member or a free function, and justify each in one line:
Catalogue::operator<<, Book::operator==, Book == std::string,
Book::operator<, Catalogue::operator[], Book::operator+= (extend a loan?),
std::ostream& operator<<(std::ostream&, const Catalogue&), Book::operator bool
("is available?").
Success looks like. Eight decisions with one-line reasons, including at least
one that reverses the obvious choice — for example making Book::operator== a free
function so that both operand orders work, or refusing Book::operator bool
because "available" is a state that belongs to a loan rather than to a book.
How you will be judged. Every reason must name either the left operand, the symmetric case, or the reader's expectation. "Style" is not a reason.
X3 — design an identifier scheme that survives two translation units [L5 Design]¶
Task. A Catalogue allocates identifiers from a class-level counter. The
program is now three files, and the counter is used from all of them. Decide how
the counter is declared, defined and initialised, and write the two files' relevant
lines.
Success looks like. A header that declares without defining, one source file that defines, and a sentence naming the One Definition Rule — plus a note on what would happen if the definition were in the header and the header were included twice.
Preview. Module 16 is the multi-file architecture this question is a first look at.
Stretch (optional)¶
- S1 — "What changes if…" the catalogue is sorted by title instead of
identifier: which of the four operators change, which callers change, and what
breaks in
std::find? - S2 — Measure
sizeoffor a type with oneintfield and one comparison operator, before and after adding astaticdata member. Explain why thestaticmember changed nothing. - S3 — Give a type
operator()and use it to sort by a caller-chosen order. This is the functor that Module 14 turns into the lambdas you have already been writing.
Solutions¶
| Exercise | Reference |
|---|---|
| W2, W4 | examples/module-05/01-static-members/main.cpp — the copy constructor that gives a copy its own serial, and the counter that outlives the objects |
| W3 | Misconceptions, Part 2 — every message above appears there with its fix |
| C1, C2 | examples/module-05/02-money-operators/main.cpp — == and < written by hand, four comparisons derived, and std::sort working with no further code |
| C3 | The same file, where inline static and an out-of-class definition both appear, with the reason for each |
| C4 | examples/module-05/03-stream-io/main.cpp for the failure-and-refusal pattern, and your own recorded observation — the experiment is the answer |
| X1, X3 | Concepts §9 and §8; X3's answer is deliberately not published, because the design is the exercise |
| X2 | Concepts §5's table is the marking scheme, not the answer |
C4 and X1 have no single published answer on purpose: one is an experiment you must run, the other is an argument you must make. Compare with the reference after writing your own.
Next: Lab 5 — make the catalogue sortable, searchable and printable, and record the comparator failure you caused on purpose. · All modules