A structured teaching repository covering modern C++ (C++20) from its C foundations through to templates, concurrency and what happens under the hood. Each topic is a folder of standalone, runnable examples with in-code commentary, built with CMake. Part of the Zero to Hero course family.
- Developers learning C++ for the first time, or coming to it from C, Java, C# or Python
- Delegates on instructor-led C++ fundamentals and intermediate courses
- Self-learners who want a clear progression from the basics to the lesser-known corners of the language
No prior C++ experience is assumed. Basic programming awareness and comfort with a command line are helpful.
| Tool | Minimum Version |
|---|---|
| CMake | 3.20 |
| One C++20 compiler: | |
| MSVC (Visual Studio 2022) | 19.30 |
| GCC | 13 |
| Clang | 17 |
cmake --version
g++ --version # or: clang++ --version, or cl (in a Developer PowerShell)GCC 13 and Clang 17 are the first versions whose standard libraries ship std::format. Ubuntu 24.04 provides GCC 13 out of the box.
- Install Visual Studio 2022 (Community is fine) with the Desktop development with C++ workload. This provides the MSVC compiler, CMake and Ninja.
- Install VS Code with the C/C++ (
ms-vscode.cpptools) and CMake Tools (ms-vscode.cmake-tools) extensions. - Clone and open the folder:
git clone git@github.com:Edrzapi/CPP_zero_hero.git
code CPP_zero_hero- When CMake Tools asks for a kit, select Visual Studio Community 2022 Release - amd64. It configures the project automatically.
- Build with F7 (or the Build button in the status bar).
- Pick an example with CMake: Set Launch/Debug Target (for example
basics_02_types_and_sizes), then run it with Shift+F5, or debug it with Ctrl+F5 and breakpoints. - Run every example as a test with CMake: Run Tests, or from the Testing panel.
Open Developer PowerShell for VS 2022 from the Start menu (it puts the compiler on PATH), then:
cd CPP_zero_hero
cmake -S . -B build # Visual Studio generator (multi-config)
cmake --build build # Debug by default
ctest --test-dir build -C Debug --output-on-failure
.\build\bin\Debug\basics_02_types_and_sizes.exePrefer single-config builds? cmake -S . -B build -G Ninja puts executables in build\bin\ directly.
MinGW-w64 (for example GCC 13+ from MSYS2 UCRT64) also works: cmake -S . -B build -G Ninja.
sudo apt update
sudo apt install build-essential cmake ninja-build gdb # GCC 13 on Ubuntu 24.04
git clone git@github.com:Edrzapi/CPP_zero_hero.git
cd CPP_zero_hero
cmake -S . -B build -G Ninja
cmake --build build
ctest --test-dir build --output-on-failure
./build/bin/basics_02_types_and_sizesTo use Clang instead: sudo apt install clang then CXX=clang++ CC=clang cmake -S . -B build-clang -G Ninja.
xcode-select --install # Apple Clang (Xcode 16 or later recommended)
brew install cmake ninja # or: brew install llvm for a newer Clang
cmake -S . -B build -G Ninja
cmake --build build
ctest --test-dir build --output-on-failure
./build/bin/basics_02_types_and_sizesNote: No third-party libraries are needed. Everything uses the C++ standard library, plus one small C library inside the repository (
c_interop/02_c_library). The practical tasks also use what the operating system already provides: SQLite (task 10; on Linux installlibsqlite3-dev), sockets (task 12) and thecurlprogram (task 12 Stretch). Their checker needs Python 3.10 or later.
|-- basics/ # Types, sizes, signed/unsigned, literals, const, references, initialisation
|-- control_flow/ # if/else, if with initialiser, switch, if constexpr
|-- iteration/ # Loops, range-for under the hood, generators (C++23)
|-- functions/ # Parameters, overloading, defaults, inline, lambdas, function pointers
|-- compilation/ # Preprocessor, translation units, headers, linkage, the ODR
| |-- 02_multi_file/ # A small static library split into headers and sources
| `-- 03_odr_violation/ # Opt-in: what breaking the One Definition Rule looks like
|-- c_interop/ # C headers, extern "C", RAII wrappers, name mangling, struct layout
| `-- 02_c_library/ # A C library (cstack.c) called from C++
|-- memory/ # Stack vs heap, RAII, smart pointers, rule of 0/3/5, move semantics
|-- oop/ # Classes, inheritance, vtables, slicing, diamonds, CRTP, operators
| `-- 08_pimpl/ # PIMPL split across header, source and program
|-- collections/ # Containers, iterators, algorithms, ranges and views, span
|-- templates/ # Function/class templates, specialisation, variadics, concepts, SFINAE
|-- exceptions/ # try/catch, custom hierarchies, error codes, optional, noexcept, expected
|-- io/ # iostreams, string streams, files, std::filesystem, std::format, std::print
|-- datetime/ # chrono durations and clocks, calendar dates, <ctime>, time zones
|-- concurrency/ # Threads, jthread, mutexes, condition variables, atomics, futures
|-- testing/ # assert, static_assert, mini_test.h harness, Calculator tests
|-- under_the_hood/ # constexpr, variant, string_view traps, attributes, placement new,
| # copy elision, SSO, compiler flags, the UB lab
|-- tasks/ # Practical tasks: the Library Manager (see Tasks below)
| |-- data/ # Shared sample data (CSV, SQL schema, recorded API response)
| |-- check/ # check.py: compares a program's output with expected.txt
| `-- 01_bookshelf/ ... 12_library_api/, B_busy_library/
| # README.md brief, expected.txt, starter/, solution/
|-- cmake/zero_hero.cmake # Shared build helpers (warnings, sanitizers, run_<topic> targets)
|-- CMakeLists.txt # Top-level build: every example, test and option
|-- main.cpp # Entry point: prints the syllabus
`-- VERIFY.md # Every target and how to build, run and check it
Files inside each folder are numbered in teaching order: 01_...cpp, 02_...cpp.
Every example is its own executable named <folder>_<file>:
cmake --build build --target basics_02_types_and_sizes
./build/bin/basics_02_types_and_sizes # Windows VS generator: .\build\bin\Debug\...Run a whole topic, in order:
cmake --build build --target run_basics # also run_control_flow, run_oop, run_templates, ...Run everything as a smoke test (each example must exit with 0):
ctest --test-dir build --output-on-failure # add -C Debug with the Visual Studio generatorRun the unit tests only, or a subset by name:
./build/bin/testing_calculator_test
./build/bin/testing_calculator_test divide # tests whose name contains "divide"| Option | Default | Effect |
|---|---|---|
CPPZH_WARNINGS_AS_ERRORS |
OFF | Adds -Werror / /WX. The whole repository builds clean with it on. |
CPPZH_ENABLE_CXX23 |
OFF | Builds the C++23 examples: std::generator, std::expected, std::print. |
CPPZH_BUILD_UB_DEMOS |
OFF | Builds the deliberate undefined behaviour demos (never part of ctest). |
CPPZH_SANITIZE |
OFF | AddressSanitizer + UBSan on GCC/Clang; AddressSanitizer only on MSVC. |
cmake -S . -B build-ub -DCPPZH_BUILD_UB_DEMOS=ON -DCPPZH_SANITIZE=ON
cmake --build build-ub --target under_the_hood_ub_examples
./build-ub/bin/under_the_hood_ub_examples use-after-free- basics: Program structure and
main, fundamental types and their platform-dependent sizes (LP64 vs LLP64), fixed-width integers, signed vs unsigned and the usual arithmetic conversions,std::cmp_less, literals andauto/decltypededuction,constvsconstexprvsconstevalvsconstinit, references vs pointers, every initialisation form and narrowing, C strings vsstd::string,enumvsenum class, the four named casts andstd::bit_cast, C arrays, decay andstd::array. - control_flow:
if/else, truthiness inherited from C, short-circuiting,ifandswitchwith initialisers (C++17), fall-through and[[fallthrough]],if constexpr. - iteration:
for,while,do-while, range-basedfor, what range-forexpands to, writing your own iterable type, the temporary-lifetime trap,std::erase_if, andstd::generator(C++23). - functions: Pass by value / reference / const reference / pointer, sink parameters, returning structs, overload resolution, default arguments, what
inlinereally means, lambdas and every capture form, dangling captures, generic lambdas,std::function, function pointers,qsortvsstd::sort, functors, member function pointers andstd::invoke.
- compilation: The preprocess / compile / assemble / link pipeline, macros and their pitfalls,
#and##, conditional compilation and compiler detection,std::source_location,assert. A multi-file static library showing include guards vs#pragma once, declarations vs definitions,externvariables, internal linkage (static, unnamed namespaces),inlinevariables, forward declarations, and the linker errors you get when each rule is broken. An opt-in ODR violation that links silently and gives wrong answers. - c_interop:
<stdio.h>vs<cstdio>,printfandsnprintf,malloc/freevsnew/delete, valid C that is not valid C++,extern "C", a C library (opaque handle, status codes) called from C++ and wrapped in an RAII class withstd::unique_ptrand a custom deleter, name mangling on Itanium and MSVC (withnm,c++filt,dumpbin,undname), struct padding andoffsetof, trivially copyable and standard-layout types, bit-fields, and when to keep C.
- memory: Automatic, dynamic and static lifetime,
new/deleteand what goes wrong with them, RAII and scope guards,unique_ptr,shared_ptr,weak_ptrand reference cycles, custom deleters, the rule of zero/three/five with a hand-written owning buffer and copy-and-swap, value categories,std::move, move-only types, and why move constructors must benoexcept. - oop: Classes vs structs, invariants,
constmember functions,mutable,staticmembers,friend, constructors in depth (initialiser lists, declaration-order initialisation, delegating,explicit), inheritance and construction order, name hiding, inherited constructors, virtual functions,override/final, abstract classes, virtual destructors, the vtable model, virtual calls during construction,dynamic_cast, object slicing and virtualclone(), multiple inheritance, the diamond and virtual inheritance, static polymorphism with CRTP, PIMPL to speed up builds, and operator overloading including<=>.
- collections:
std::vector(capacity, invalidation,erase),deque,list,forward_list,stack,queue,priority_queue,map/setand the unordered containers with a custom hash, iterator categories and adaptors, the classic algorithms, C++20 ranges, projections and lazy views, andstd::span. - templates: Function and class templates, deduction, non-type parameters, abbreviated templates, CTAD and deduction guides, full and partial specialisation, writing type traits, variadic templates, fold expressions, perfect forwarding, concepts and
requiresclauses, overloading on constraints, and SFINAE (enable_if,void_t) with why concepts replaced it. - exceptions:
throw/try/catch, the standard hierarchy, stack unwinding, rethrowing, a three-level custom hierarchy (as in Java Zero to Hero), nested exceptions, error codes anderrno,std::from_chars,std::error_code,std::optional,noexcept, the basic/strong/nothrow guarantees, andstd::expected(C++23). - io: Standard streams and manipulators, validating input and stream state, string streams for building and parsing text, text and binary files,
std::filesystem,std::formatwith custom formatters, andstd::print(C++23). - datetime:
std::chronodurations, clocks and time points, C++20 calendar types and date arithmetic, the C<ctime>API and bridging tochrono, and time zones (guarded by a feature-test macro where library support is missing). - concurrency:
std::thread,std::jthreadandstop_token, passing arguments, exceptions across threads,mutex,lock_guard,unique_lock,scoped_lockand deadlock avoidance,shared_mutex, a blocking producer/consumer queue withcondition_variable, atomics,compare_exchange, memory orders,atomic_flag,std::async, futures, promises andpackaged_task. An opt-in data race demo (the C++ version of Java'sRaceConditionRunner).
- testing:
assertandstatic_assert, a tiny self-contained test harness (mini_test.h) that shows how frameworks work inside, and aCalculatortest suite with fixtures, table-driven tests, floating-point tolerance and exception checks. The comments show the same tests in GoogleTest and Catch2 and how to add either with CMakeFetchContent.
- under_the_hood: Compile-time lookup tables,
constexprstd::vector/std::string(C++20),constevalswitch labels,std::is_constant_evaluated, structured bindings and the tuple protocol,std::variant/std::visitvs virtual functions,std::any,std::string_viewlifetime traps, standard attributes, user-defined literals and strong types, placementnew,std::launderand alignment, copy elision (RVO and NRVO), the small string optimisation measured by replacingoperator new, compiler warning flags, sanitizers and Compiler Explorer tips. The opt-in UB lab has ten bugs to run under AddressSanitizer and UBSan.
The tasks/ folder holds the Library Manager, one practical project shared by every Zero to
Hero repo: 12 tasks and a bonus in Python, Java, C#, C++ and JavaScript, and eight tasks (S1 to S8) in SQL's own
order on the same database. Every repo uses the same briefs, the same sample data and the same expected output; only
the code differs.
- One task per session. Each task is the end-of-session check and builds on the one before, so by the end the learner has one working program.
- Three levels: Core (everyone), Stretch (for those who finish early) and Challenge (the strongest learners, or homework).
- Every task folder has the brief (
README.md), the exact expected output (expected.txt), astarter/that runs as it is (unfinished parts say "not implemented") and asolution/with Core and Stretch. - One checker:
tasks/check/check.py(Python 3.10 or later, standard library only) runs a program and printsPASS, orFAILwith the first line that differs fromexpected.txt. On Windows,pyworks in place ofpython.
tasks/README.md has the session to task map, the 3-day and 5-day selections, and the run and check command for every task. To check the first task's solution, from the repo root:
cmake --build build --target task01_solution && python tasks/check/check.py 01 -- build/bin/task01_solution- Every file is a standalone, runnable program with its own build target
- Concepts are explained in comments alongside working code; the output each line prints is noted where it helps
- Mistakes are shown next to the correct approach, as commented-out code, so the build stays clean
- Undefined behaviour is never part of the default build: it lives in clearly labelled, opt-in targets
- Topics progress from the C heritage through modern C++ to the lesser-known material
- No third-party libraries: the focus is on the language and the standard library
| Technology | Purpose |
|---|---|
| C++20 | Language (C++23 examples are opt-in and clearly marked) |
| C11 | The small C library in c_interop/ |
| CMake 3.20+ | Build system (Ninja or Visual Studio generators) |
| CTest | Runs every example and the unit tests |
| mini_test.h | In-repo test harness (no download) |
| MSVC, GCC, Clang | Supported compilers |
No Boost. No Qt. No package managers. No third-party test frameworks.
This course covers C++ from its C foundations to modern C++20. For the same structured approach in other languages, see the companion repositories: