← Back to C++ Course | Chapter 16: Modern C++ | Lesson 8 of 9

C++ Modules (C++20)

Understanding Modular Design

C++20 Modules are a modern replacement for the traditional #include header system, designed to speed up compilation and give each file explicit, isolated control over what it exposes to the rest of the program.

Example: Understanding Modular Design

cpp
// math.cppm -- a C++20 module file
export module math;

export int add(int a, int b) {
	return a + b;
}

// main.cpp would then say: import math;  add(2, 3);

Why Modules are Better than Headers

Traditional headers rely on the preprocessor literally copy-pasting their entire contents into every file that includes them, which means the same declarations get re-parsed over and over across a large codebase. Modules are compiled once into an efficient binary interface file that's then loaded directly, without re-parsing.

Example: Why Modules are Better than Headers

cpp
// shapes.cppm
export module shapes;

export class Circle {
public:
	double radius;
};

// Unlike a #include'd header, this isn't re-parsed textually by every
// importing file -- the compiler processes it once and reuses the result.

C++20 export and import syntax

You define a module with export module ModuleName; at the top of a source file, marking specific declarations with export to make them part of the module's public interface. Any file that wants to use it writes import ModuleName; instead of an #include directive.

Example: C++20 export and import syntax

cpp
// greet.cppm
export module greet;

export void sayHello() {
	// prints a greeting
}

// main.cpp:
// import greet;
// int main() { sayHello(); }

Preventing Symbol Collisions

Unlike headers, anything declared inside a module but not explicitly marked export stays entirely private to that module -- it can't leak into or collide with names in files that import it, which eliminates a whole category of naming conflicts common in large header-based projects.

Example: Preventing Symbol Collisions

cpp
// mathutils.cppm
export module mathutils;

int internalHelper(int x) { // not exported: stays private to this module
	return x * 2;
}

export int doubleValue(int x) {
	return internalHelper(x);
}

Modular Best Practices

Well-designed modules keep their exported interface small and deliberate -- only genuinely public functions and types should be exported, while internal helper functions and implementation details stay unexported, mirroring the public/private discipline you'd apply inside a class.

Example: Modular Best Practices

cpp
// account.cppm
export module account;

double calculateFee(double amount) { // internal detail, not exported
	return amount * 0.02;
}

export double totalWithFee(double amount) { // small, deliberate public interface
	return amount + calculateFee(amount);
}

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.