Modern C++ is a collection of deep, code-first documentation for the C++ language as it exists today — C++11 through C++23. Every page is built around complete, working programs. Samples marked with a Run in Compiler Explorer link open directly in Compiler Explorer with the right flags already set, so you can run and modify them in one click. Everything on this site compiles cleanly with -std=c++23 -Wall -Wextra.
Features are labeled with the standard that introduced them, like this: C++23. If a page covers a feature that changed across standards, each refinement is labeled where it appears.
Core language features
How to write today's C++ at the language level: type deduction, initialization, enumerations, iteration, conversions, namespaces, and the deduction machinery that removes boilerplate.
- Using auto whenever possible
Deduce types instead of spelling them: locals, qualifiers, return types, generic lambdas — and the cases where auto surprises you.
- Creating type aliases and alias templates
The using declaration as the full replacement for typedef, and alias templates for parameterized names.
- Understanding uniform initialization
Brace initialization for every kind of object, narrowing protection, the initializer_list trap, and designated initializers.
- Non-static member initialization
Default member initializers, constructor initializer lists, initialization order, and which form to use when.
- Controlling and querying object alignment
alignas and alignof, why alignment exists, over-aligned types, and cache-line-aware layout.
- Using scoped enumerations
enum class: real scoping, no implicit conversions, chosen underlying types, using enum, and std::to_underlying.
- Virtual methods with override and final
Making the compiler verify your overrides, sealing hierarchies, and the bugs these two words eliminate.
- Iterating with range-based for loops
What the loop actually expands to, choosing the right element binding, init-statements, and C++23's temporary-lifetime fix.
- Enabling range-based for on your own types
The exact protocol the compiler looks for, writing a minimal iterator, and sentinel-terminated ranges.
- Avoiding implicit conversion with explicit
Converting constructors, conversion operators, the bugs implicit conversions cause, and conditional explicit(bool).
- Unnamed namespaces instead of static globals
Internal linkage done right: per-file helpers, ODR safety, and why static at namespace scope is the weaker tool.
- Inline namespaces and symbol versioning
Publishing versioned APIs under one name, how the standard library uses them, and ABI-safe evolution.
- Structured bindings and multiple return values
Decomposing pairs, tuples, structs, and arrays; returning multiple values without out-parameters.
- Class template argument deduction
Letting the compiler deduce class template arguments, writing your own deduction guides, and knowing when to opt out.
- The subscript operator, from operator[] to C++23
Writing correct subscript access for your own collections, const and non-const pairs, multidimensional operator[], and deducing this.
Numbers and strings
Working with data's two most common shapes: numeric types and their properties, text in all its encodings, randomness done right, user-defined literals, regular expressions, and the modern formatting stack.
- Understanding the various numeric types
Fundamental integers and floats, fixed-width aliases, mixed-sign traps, and modern literal syntax.
- Limits and other properties of numeric types
std::numeric_limits: min, max, lowest, epsilon, precision digits — and putting each to work correctly.
- Understanding the various character and string types
char through char32_t, five literal encodings, code units vs characters, and which string to actually use.
- Printing Unicode characters to the console
Getting UTF-8 from source to terminal intact, platform setup, escapes, and normalization surprises.
- Generating pseudo-random numbers
The engine-plus-distribution design of <random>, choosing each, and why rand() is never the answer.
- Properly initializing a pseudo-random number generator
random_device, seed_seq, full-state seeding, and treating seeds as reproducibility data.
- Creating cooked user-defined literals
Literal operators that attach units to values — 64_KiB, 90.0_deg — with compile-time validation.
- Creating raw user-defined literals
Operators that see the literal's original spelling: exact decimals, other bases, per-digit validation.
- Using raw string literals to avoid escaping characters
R"(...)" syntax, custom delimiters, multi-line text, and why every regex belongs in one.
- Creating a library of string helpers
trim, case mapping, split, join, replace_all — the missing std::string utilities, built correctly once.
- Parsing the content of a string using regular expressions
regex_match vs regex_search, capture groups, iterating matches, and honest performance guidance.
- Replacing content of a string using regular expressions
regex_replace, backreferences, format flags, and the callback pattern the standard forgot.
- Using std::string_view instead of constant string references
The non-owning parameter type, allocation-free parsing, and the lifetime rules that keep it safe.
- Formatting and printing text with std::format and std::print
The {} mini-language, compile-time checked format strings, and C++23's print family.
- Using std::format with user-defined types
Specializing std::formatter: the delegation shortcut, custom specs, and range formatting.
Coming soon
Phases 1 and 2 cover core language features and working with numbers and strings. Future phases will go equally deep on the standard library containers and algorithms, ranges, general-purpose utilities, and threading and concurrency.
External references
- cppreference.com
The community reference for the C++ language and standard library.
- Compiler support tables
Which compiler versions implement each C++20/C++23 feature.
- Working draft of the C++ standard
The language, straight from the source.