5.2.32 · D3C++ Programming

Worked examples — Modules (C++20) — concept and syntax

4,091 words19 min readBack to topic

Prerequisite ideas we lean on: The C++ Preprocessor (what #include really does), Translation Units and Linkage (what a "compiled unit" is), Namespaces in C++ (a different axis of visibility), Module Partitions (splitting one module across files), and Build Systems and Compilation Speed (why any of this matters).


First: the anatomy of a module file

Two phrases appear in every example below — global module fragment and named-module region — so let us pin them to a picture before we use them. The line that opens the fragment is the bare word module; — one token, a semicolon, nothing else — so define it before we lean on it.

Figure — Modules (C++20) — concept and syntax

In the figure, follow the plum-shaded band (the fragment / airlock, opened by module;) and the teal region below the dividing line (the named module). Every later example is just a variation on where a line falls relative to that dividing line.


The scenario matrix

Here is the full space of cases a module topic can throw at you. Every cell below is covered by at least one worked example — the example numbers are in brackets.

Axis Case class Covered by
Export position single export on one declaration E1
export { ... } block (group) E1
no export → private name E1, E2
#include placement legal: inside global module fragment E3
illegal: after export module E3
degenerate: no fragment needed at all E1
File roles one file does everything (interface = implementation) E1
split: interface unit + implementation unit E4
Boundary confusion export vs class public/private E5
Multiplicity two files claim same export module (error) E6
correct fix: partitions E6
Macros macro leakage: does import carry it? (no) E7
header unit import "h.h" does carry it E7
Standard library import std; / header units vs #include E7
Real-world word problem build-speed estimate: parse-once payoff E8
Exam twist trace what compiles / what's visible where E2, E5, E9

E1 — Baseline: single, group, and private (cell: export position + degenerate no-fragment)

Figure — Modules (C++20) — concept and syntax

E2 — Forecast trap: touching a private name (cell: no-export → error)


Figure — Modules (C++20) — concept and syntax

E4 — Split interface / implementation (cell: two file roles)

Figure — Modules (C++20) — concept and syntax

E5 — export vs public collision (cell: boundary confusion / exam twist)


E6 — Duplicate interface vs partitions (cell: multiplicity)


E7 — Macros, header units, and the standard library (cell: macro leakage + import std)


E8 — Real-world word problem: build-speed payoff (cell: word problem)


E9 — Exam twist: full visibility trace (cell: exam-style)


Active recall

Recall Answer before expanding

What is the bare module; line (no name) for, and what breaks if you omit it? ::: It opens the global module fragment; omit it and you have nowhere legal to write a #include (E1, E3). Where is the ONLY legal spot for #include in a module file? ::: In the global module fragment, between module; and export module Name; (E3). A private member of an exported class — visible to importers? ::: No; the class door (public) blocks it even though the module door (export) is open (E5). Does import lib; bring in lib's macros? ::: No — a named-module import exports no macros; use a header unit import "h.h"; if you truly need them (E7). Header unit vs named-module import — which keeps macros? ::: The header unit (import "h.h";) keeps macros; the named-module import (import util;) does not (E7). Two files both write export module shape; — legal? ::: No; a module has exactly one primary interface unit. Use partitions export module shape:part; (E6). A header parsed 0.5 s, included in 200 units — #include vs module parse totals? ::: s vs s, a saving (E8).