CodeRigor

FREE COURSE / REAL PRACTICE

C++ Core Guidelines

Apply selected C++ Core Guidelines through bounded interfaces, ownership, enum design, polymorphism and exception guarantees.

Free lessons & exercises38 authored lessons19 units

What you’ll work toward

Explain and test representative design contracts, and connect the selected rules to the broader guidelines reference.

Read an explanation, inspect the diagrams and work through the available checks, debugging exercises and builds. Feedback and prerequisite links guide the next step.

Before you start

The entry lesson has no earlier CodeRigor skill prerequisite. Start there and follow the sequence.

Individual lessons can add prerequisites. The course map shows your actual readiness.

A look inside the first lesson

Values, references and const

C++
#include <print>
#include <string>

int main() {
    std::string a = "hello";
    std::string b = a;      // b is a copy
    b += ", world";
    std::println("a = {}, b = {}", a, b);   // a is unchanged
}

Your course outline

Follow the lessons in curriculum order. Open a unit to preview the ideas you’ll work with.

UNIT 013 lessons Foundations
  1. LESSON 01.01

    Values, references and const

    Choose deliberately between copying, aliasing and pointing; write const-correct APIs; never let a reference outlive its object.

    Open lesson
  2. LESSON 01.02

    std::vector, std::span and std::string_view

    Own sequences with std::vector, pass them around with std::span and std::string_view, and never let a view outlive what it looks at.

    Open lesson
  3. LESSON 01.03

    RAII, scope and object lifetime

    Tie every resource to an object's lifetime so cleanup happens exactly once — on normal exit, early return and exceptions.

    Open lesson
UNIT 022 lessons Owning things
  1. LESSON 02.01

    Classes: invariants and the rule of zero/five

    Design classes that establish and keep an invariant, let the compiler write the special members (rule of zero), and know exactly when it can't.

    Open lesson
  2. LESSON 02.02

    Move semantics and value categories

    Know which expressions can be moved from, write correct noexcept move operations, and know when the compiler elides copies for you.

    Open lesson
UNIT 033 lessons Generic code
  1. LESSON 03.01

    Templates and concepts

    Write generic code that says what it needs: templates, deduction, concepts and requires-clauses, folds, and C++26 pack indexing.

    Open lesson
  2. LESSON 03.02

    Iterators and ranges basics

    Know what each iterator category promises, make your own container work with std::ranges, and use sentinels, projections and simple views.

    Open lesson
  3. LESSON 03.03

    Errors as values: optional and expected

    Return "maybe a value" and "a value or an error" as types, chain them without nested ifs, and know when an exception is the better tool.

    Open lesson
UNIT 042 lessons Hashing and heaps
  1. LESSON 04.01

    Smart pointers and ownership

    Decide who owns what — unique, shared or borrowed — and express it with unique_ptr, shared_ptr, weak_ptr and plain references, without leaks, cycles or double frees.

    Open lesson
  2. LESSON 04.02

    Lambdas and callables

    Write lambdas with deliberate captures, and pick the right callable type for an API: a template, std::function_ref, std::function or std::move_only_function.

    Open lesson
UNIT 052 lessons Compile time and trees
  1. LESSON 05.01

    Compile-time programming

    Move work to compile time with constexpr, consteval and constinit — and let the compiler reject undefined behaviour for you.

    Open lesson
  2. LESSON 05.02

    std::format and std::print

    Type-safe, compile-time-checked formatting: the replacement-field grammar, ranges, allocation-free output, runtime patterns, and custom formatters.

    Open lesson
UNIT 062 lessons Sum types, contracts, graphs
  1. LESSON 06.01

    Sum types and value-semantic polymorphism

    Model closed sets of alternatives with std::variant and exhaustive visitors, build recursive value types with std::indirect, and get copyable open hierarchies with std::polymorphic instead of unique_ptr plus clone().

    Open lesson
  2. LESSON 06.02

    Contracts (C++26)

    State what callers must ensure and what a function promises with pre, post and contract_assert — and know exactly what happens when they're broken.

    Open lesson
UNIT 072 lessons Pipelines and memory
  1. LESSON 07.01

    Ranges: views and pipelines

    Compose lazy views with |, materialise with ranges::to, fold, generate with std::generator, and know where views dangle or cache.

    Open lesson
  2. LESSON 07.02

    Memory layout, alignment and caches

    Know what your objects look like in memory: padding and member order, alignment, empty members, object representation without UB, and laying data out for the cache.

    Open lesson
UNIT 084 lessons Concurrency
  1. LESSON 08.01

    Threads, jthread and cooperative cancellation

    Start, stop and join threads safely: jthread and stop tokens for cancellation, mutexes and condition variables without races or deadlocks, futures for results.

    Open lesson
  2. LESSON 08.02

    Atomics and the C++ memory model

    Share data between threads without locks: atomic operations, compare-exchange loops, and the memory orders (relaxed, acquire/release, seq_cst) that decide what other threads are guaranteed to see.

    Open lesson
  3. LESSON 08.03

    std::execution: senders and receivers

    Understand C++26's async model — lazy senders, receivers with three completion channels, operation states — by building a small standards-shaped implementation of just, then, when_all and sync_wait.

    Open lesson
  4. LESSON 08.04

    Safe memory reclamation: hazard pointers and RCU

    Free nodes of a lock-free structure safely and promptly: hazard pointers that protect what a thread is reading, and epoch-based RCU that frees an old version only after every reader that could see it has moved on.

    Open lesson
UNIT 092 lessons Performance
  1. LESSON 09.01

    Profiling and benchmarking

    Measure before optimising: honest timing loops, the right statistic, keeping the optimiser from deleting your benchmark, and reading perf counters.

    Open lesson
  2. LESSON 09.02

    Data-oriented design

    Design around the data and how it's accessed: hot/cold splits, struct-of-arrays, dense storage with generational handles instead of pointers, batching by type, and branch-friendly data.

    Open lesson
UNIT 101 lesson Microcontrollers: the bare machine
  1. LESSON 10.01

    Memory-mapped I/O and volatile

    Talk to hardware through memory-mapped registers: what volatile guarantees (and doesn't), register structs, read-modify-write and write-1-to-clear registers, why bitfields and hardware don't mix, and a polling UART driver.

    Open lesson
UNIT 112 lessons Production C++: build, test, debug, ship
  1. LESSON 11.01

    Building real C++ projects: translation units, linking and CMake targets

    How a multi-file C++ project becomes binaries: headers and the ODR, reading linker errors, static vs shared libraries, and target-based CMake — usage requirements, presets, packages and compile_commands.json.

    Open lesson
  2. LESSON 11.02

    Testing a C++ project: CTest, fixtures and golden images

    Test a real C++ library the way production teams do: CTest labels and fixtures, doctest, deterministic fixtures from a specified PRNG, golden images with documented tolerances, regression tests from observed failures, test seams and malformed input.

    Open lesson
UNIT 121 lesson Unix/Linux: files, descriptors & filesystem
  1. LESSON 12.01

    Descriptors & open file descriptions

    Own Linux descriptors in C++: move-only RAII, atomic close-on-exec duplication, shared offsets and status flags, independent descriptor flags and errno-safe cleanup.

    Open lesson
UNIT 131 lesson Standard containers: contracts, bits & duplicate keys
  1. LESSON 13.01

    Standard containers: identity, transfer & invalidation

    Apply list splice, forward_list erasure, map node handles and borrowed array views; choose storage by ownership and stability guarantees.

    Open lesson
UNIT 141 lesson Shaped views & stable block storage
  1. LESSON 14.01

    hive storage: stable entities with the reference implementation

    Practice stable insertion and erasure using pinned plf::hive, with a consistent id index and lifetime checks. Native std::hive remains unavailable here.

    Open lesson
UNIT 152 lessons C library: bytes, strings & characters
  1. LESSON 15.01

    Byte buffers & memory functions

    Validate byte ranges before calling memmove; distinguish overlap, byte counts and object representation from typed value operations.

    Open lesson
  2. LESSON 15.02

    C strings, terminators & bounded adapters

    Keep byte length, buffer capacity and NUL termination distinct; use memchr to inspect bounded storage and copy text without silent truncation.

    Open lesson
UNIT 163 lessons C library: conversion, allocation & streams
  1. LESSON 16.01

    Checked numeric conversion & errno

    Combine strtol/strtod, end pointers, errno and destination bounds; reject incomplete tokens, embedded NUL, whitespace, overflow and nonfinite numbers.

    Open lesson
  2. LESSON 16.02

    malloc, calloc, realloc & ownership

    Own C-allocated byte storage, check size products before allocation, preserve the old block on realloc failure and release with the matching allocator.

    Open lesson
  3. LESSON 16.03

    FILE streams, buffering & binary I/O

    Use fread/fwrite counts, distinguish EOF from stream errors, and flush buffered output while keeping FILE ownership explicit.

    Open lesson
UNIT 171 lesson C library: formatting, callbacks & time
  1. LESSON 17.01

    Format strings, snprintf & bounded input

    Match variadic format arguments exactly, interpret snprintf counts and truncation, and separate trusted formats from input data.

    Open lesson
UNIT 182 lessons Core Guidelines: interfaces, expressions & enums
  1. LESSON 18.01

    Core Guidelines: explicit, bounded interfaces

    Design APIs that carry argument roles, bounds, ownership and failure policy; validate borrowed input before returning owned domain values.

    Open lesson
  2. LESSON 18.02

    Core Guidelines: checked expressions and scoped enums

    Initialize before use, validate arithmetic and conversions before evaluation, and represent enum domains with explicit checked boundaries.

    Open lesson
UNIT 192 lessons Core Guidelines: class design & exception guarantees
  1. LESSON 19.01

    Core Guidelines: polymorphic interfaces without slicing

    Choose value types or abstract interfaces deliberately; prevent slicing, preserve dynamic types through clone, and copy owned operations safely.

    Open lesson
  2. LESSON 19.02

    Core Guidelines: exception guarantees and commit points

    State the basic, strong and no-throw guarantees; stage fallible work under RAII and commit without changing promised state on failure.

    Open lesson