Final project: a catalog and a warehouse
What you'll learn:
- combine a container, strings and
constmethods in one class; - write methods that return
falseand change nothing when they refuse; - change the elements of a vector in a range-for loop through a reference;
- read the output of the checks and start with the first failed one.

Picture a librarian at the desk. In front of them is a drawer of book cards, one card per book. A reader brings a slip with a book's number. The librarian finds its card and checks whether it carries a "lent" stamp. If the stamp is already there, the librarian hands the slip back with a refusal and touches nothing in the drawer.
A class in a real program works the same way: it keeps data in a container, takes a request and checks whether the operation is allowed. The analogy differs from the code in one point: a method does not explain why it refuses; it only returns false. The two exercises of the final project are exactly like that: they introduce no new constructs; you combine familiar ones.
Two exercises
The catalog keeps books—Book structs with a number, a title, an author and a lent-out flag. It finds an author's books, lends a book out by its number and takes it back. The warehouse counts how many units of each item it holds. An item may be a string, a number or a value of another type, so the warehouse is a class template.
| Exercise | What it needs |
|---|---|
| Book catalog | a class, const methods, std::vector, std::string and std::string_view |
| Generic warehouse | a class template, a const method, std::map |
An operation can be impossible: lending a book that is already lent out, or taking more than there is. Then the method returns false and changes nothing.
How to proceed
Start with the fields and the add method: without them, the other methods have nothing to work with. Then write one method at a time and run the tests after each.
The tests call the methods in turn, and the result of each call depends on the calls before it. So start with the first failed check: the ones after it often fail because of it.
Reading a check
A check that passes prints nothing. A check that fails prints a line marked ✗. This is how the warehouse stub answers the first check:
✗ fruit.count("apple") == 8 got: -1A ✗ line has three parts:
- left of
==, the call from the test; - right of
==, the expected value; - after
got:, what your code returned.
Here -1 comes from the stub: the count method is not written yet. Below the line are the test file's name and the line where the check is written.
Besides such lines, you will see three other kinds of messages:
- a check of a condition, such as
✗ fruit.take("apple", 6), has nogot:part: the condition turned out false, sotakereturnedfalse; - the summary "Passed n of m" shows how many checks passed;
- if the program stops abnormally, the line "During check" names the check where it happened.
Common mistake
A range-for loop is meant to change the elements of a vector, but the loop variable is declared without &:
#include <iostream>
#include <vector>
struct Book {
int id;
bool lent = false;
};
int main() {
std::vector<Book> books{{1}, {2}};
for (Book book : books) { // ✗
book.lent = true;
}
std::cout << books[0].lent << ' ' << books[1].lent << '\n'; // 0 0
}The program builds and prints 0 0: on each iteration, book is a copy of the element, and the copy gets true. In the catalog, the tests reveal this mistake: lending the same book a second time returns true again.
Declare the loop variable as a reference: for (Book& book : books). Then the loop changes the elements themselves, and the program prints 1 1.
Press "Next step" and watch books[0]: in the first loop true goes to the copy book, in the second to the element itself.
1–3#include <iostream>, <vector>4struct Book {5 int id;6 bool lent = false;7};8 9int main() {10 std::vector<Book> books{{1}, {2}};11 for (Book book : books) {12 book.lent = true;13 }14 std::cout << books[0].lent << "\n";15 for (Book& book : books) {16 book.lent = true;17 }18 std::cout << books[0].lent << "\n";19}
A vector of two books, neither lent out
Key points
- The classes of the final project are built from familiar constructs: a container, strings and
constmethods. - A method that refuses returns
falseand changes nothing. - For a range-for loop to change the elements, declare the loop variable as a reference:
Book& book. - Start with the first failed check: the ones after it often fail because of it.
Subscribe to take the course
The course is free. Sign in with Telegram and subscribe to the channel to open every lesson.