Modules
Modern C++20 module system for better code organization
📦 What are C++ Modules?
Modules provide a modern alternative to header files, offering better compilation times, stronger encapsulation, and cleaner interfaces while eliminating many preprocessor-related issues.
// math_utils.cppm (module interface)
export module math_utils;
export int add(int a, int b) {
return a + b;
}
Key Concepts
export
Make declarations visible
export int function();
import
Use module functionality
import math_utils;
Module Interface
Public module declarations
export module my_module;
Module Implementation
Private module details
module my_module;
🔹 Basic Module Example
C++20 modules replace traditional header files for faster compilation and better encapsulation. A
module is declared with export module name; and can export functions, classes, and templates. Importing
with import name; gives access only to the exported interface, not implementation details. This reduces
compilation times by eliminating redundant parsing of headers and prevents macro pollution. Modules represent a
major shift toward more robust, scalable, and efficient C++ code organization.
🔸 Module Interface (math_utils.cppm)
// math_utils.cppm - Module interface unit
export module math_utils;
// Export functions
export int add(int a, int b);
export int multiply(int a, int b);
// Export class
export class Calculator {
public:
int add(int a, int b);
int subtract(int a, int b);
private:
int history_count = 0; // Not exported
};
// Private helper function (not exported)
int validate_input(int x) {
return x < 0 ? 0 : x;
}
🔸 Module Implementation (math_utils.cpp)
// math_utils.cpp - Module implementation unit
module math_utils;
// Implement exported functions
int add(int a, int b) {
return validate_input(a) + validate_input(b);
}
int multiply(int a, int b) {
return validate_input(a) * validate_input(b);
}
// Implement exported class methods
int Calculator::add(int a, int b) {
history_count++;
return a + b;
}
int Calculator::subtract(int a, int b) {
history_count++;
return a - b;
}
🔸 Using the Module (main.cpp)
// main.cpp - Using the module
import math_utils;
#include <iostream>
int main() {
// Use exported functions
std::cout << "5 + 3 = " << add(5, 3) << std::endl;
std::cout << "4 * 6 = " << multiply(4, 6) << std::endl;
// Use exported class
Calculator calc;
std::cout << "Calculator: 10 + 5 = " << calc.add(10, 5) << std::endl;
std::cout << "Calculator: 10 - 3 = " << calc.subtract(10, 3) << std::endl;
return 0;
}
Output:
5 + 3 = 8 4 * 6 = 24 Calculator: 10 + 5 = 15 Calculator: 10 - 3 = 7
🔹 Module Partitions
Module partitions organize large modules into logical, manageable subunits. A primary module
interface can be split into partition files (e.g., module name:part1;). These partitions are private to
the module, allowing internal reorganization without affecting users. This maintains a clean public API while
managing complexity. Partitions are essential for large libraries or components, enabling teams to work on different
internal sections without creating tight coupling or exposing internal implementation details.
🔸 Primary Module Interface (graphics.cppm)
// graphics.cppm - Primary module interface
export module graphics;
// Export partitions
export import :shapes;
export import :colors;
// Additional exports from primary interface
export void initialize_graphics() {
// Setup code
}
🔸 Shapes Partition (graphics-shapes.cppm)
// graphics-shapes.cppm - Module partition
export module graphics:shapes;
export class Circle {
public:
Circle(double radius) : radius_(radius) {}
double area() const { return 3.14159 * radius_ * radius_; }
private:
double radius_;
};
export class Rectangle {
public:
Rectangle(double width, double height)
: width_(width), height_(height) {}
double area() const { return width_ * height_; }
private:
double width_, height_;
};
🔸 Colors Partition (graphics-colors.cppm)
// graphics-colors.cppm - Module partition
export module graphics:colors;
export enum class Color {
Red, Green, Blue, Yellow, Black, White
};
export class ColorPalette {
public:
void set_primary(Color c) { primary_ = c; }
Color get_primary() const { return primary_; }
private:
Color primary_ = Color::Black;
};
🔸 Using Partitioned Module
// main.cpp - Using partitioned module
import graphics; // Imports all partitions
#include <iostream>
int main() {
initialize_graphics();
Circle circle(5.0);
Rectangle rect(4.0, 6.0);
std::cout << "Circle area: " << circle.area() << std::endl;
std::cout << "Rectangle area: " << rect.area() << std::endl;
ColorPalette palette;
palette.set_primary(Color::Blue);
return 0;
}
Output:
Circle area: 78.5397 Rectangle area: 24
🔹 Modules vs Headers
Modules provide significant advantages over traditional header files in modern C++ development. They
eliminate the need for include guards, reducing macro collisions and enforcing clear separation between interface
and implementation. Compilation is substantially faster because modules are parsed once into optimized binary form,
rather than repeatedly processing headers. Modules also strengthen tooling by providing precise dependency
definitions. While headers remain supported for legacy code, adopting export module and
import syntax leads to cleaner, more maintainable code, dramatically faster build times, and superior
encapsulation—especially beneficial in large-scale projects where compilation overhead becomes critical.
Traditional Headers:
- Textual inclusion: Code copied into each translation unit
- Multiple inclusion: Requires include guards
- Macro pollution: Macros can affect other code
- Slow compilation: Headers parsed repeatedly
Modern Modules:
- Semantic import: Pre-compiled module interfaces
- No redefinition: Modules imported once
- Macro isolation: Macros don't leak between modules
- Fast compilation: Modules compiled once, reused
🔸 Header Style (Old)
// utils.h
#ifndef UTILS_H
#define UTILS_H
#define PI 3.14159 // Can pollute other files
int square(int x);
#endif
🔸 Module Style (New)
// utils.cppm
export module utils;
// Macros are module-private by default
#define PI 3.14159
export int square(int x) {
return x * x;
}