# Modules (C++)

**Modules** are a C++20 language feature that replaces the header-file model of sharing declarations between translation units. Instead of pasting header text into every file that `#include`s it, a module explicitly exports declarations, and the compiler stores them in a machine-readable binary form that other files load with an `import` declaration. The feature consists of two parts, named modules and header units, and was merged into the C++20 committee draft in 2019 after more than a decade of design work.<sup>[1](https://en.cppreference.com/cpp/language/modules)</sup><sup> • </sup><sup>[2](https://clang.llvm.org/docs/StandardCPlusPlusModules.html)</sup><sup> • </sup><sup>[3](https://meetingcpp.com/mcpp/slides/2019/modules-the-beginners-guide-meetingcpp2019.pdf)</sup>

| Key fact | Detail |
|---|---|
| Standardized in | C++20; the fused Modules proposal (P1103) was merged into the C++20 committee draft in 2019<sup>[3](https://meetingcpp.com/mcpp/slides/2019/modules-the-beginners-guide-meetingcpp2019.pdf)</sup> |
| Two components | Named modules and header units<sup>[2](https://clang.llvm.org/docs/StandardCPlusPlusModules.html)</sup> |
| Module structure | A named module is the collection of module units sharing one module name; exactly one interface unit without a partition is the primary module interface unit<sup>[1](https://en.cppreference.com/cpp/language/modules)</sup> |
| What is exported | Declarations marked with `export` (or inside an `export { }` block); macros are never exported<sup>[1](https://en.cppreference.com/cpp/language/modules)</sup><sup> • </sup><sup>[4](https://learn.microsoft.com/en-us/cpp/cpp/modules-cpp)</sup> |
| Build artifact | A binary module interface (BMI): `.ifc` for MSVC, `.pcm` for Clang; BMIs are not portable across compilers or flags<sup>[5](https://learn.microsoft.com/en-us/cpp/build/compare-inclusion-methods?view=msvc-170)</sup><sup> • </sup><sup>[6](https://libcxx.llvm.org/Modules.html)</sup> |
| Compile-time model | The compiler emits a structured, order-independent, macro-independent representation that loads quickly on import, instead of re-preprocessing and recompiling header text in every translation unit<sup>[5](https://learn.microsoft.com/en-us/cpp/build/compare-inclusion-methods?view=msvc-170)</sup> |
| Standard library | `import std;` and `import std.compat;` are standardized and fully implemented in MSVC since Visual Studio 2022 17.5; libc++ support is experimental<sup>[4](https://learn.microsoft.com/en-us/cpp/cpp/modules-cpp)</sup><sup> • </sup><sup>[6](https://libcxx.llvm.org/Modules.html)</sup> |

## Structure of a named module

A module consists of one or more **module units**, which are translation units that begin with a module declaration:

```
[export] module module_name[:partition_name];
```

Module units whose declaration carries the `export` keyword are module interface units; all others are module implementation units. For every named module there must be exactly one interface unit that specifies no partition, the primary module interface unit; its exported content is what importers of the module see.<sup>[1](https://en.cppreference.com/cpp/language/modules)</sup>

The module name consists of one or more identifiers separated by dots, such as `mymodule.mysubmodule`. The dots have no intrinsic meaning and do not create a hierarchy, although they are used informally to suggest one. If any identifier in the module name or partition is defined as an object-like macro, the program is ill-formed.<sup>[1](https://en.cppreference.com/cpp/language/modules)</sup>

**Exporting.** Interface units export declarations by prefixing them with `export` or placing them in an `export { }` block. In the cppreference example, `export char const* hello() { return "hello"; }` is visible to importers while an unexported `world()` in the same unit is not; exporting a namespace makes all its listed members visible. Names that are not exported remain internal to the module.<sup>[1](https://en.cppreference.com/cpp/language/modules)</sup> Microsoft's documentation adds the practical consequence that a macro such as `#define ANSWER 42` in an interface unit is invisible to importers, because macros are not exported.<sup>[4](https://learn.microsoft.com/en-us/cpp/cpp/modules-cpp)</sup>

**Partitions and fragments.** A module can be split into partitions (`module A:B;`), and an interface unit may contain a private module fragment, introduced with `module : private;`, which ends the portion of the interface that can affect other translation units; a unit with a private module fragment is the only module unit of its module.<sup>[1](https://en.cppreference.com/cpp/language/modules)</sup>

## Header units and the global module fragment

A header unit wraps an existing header file so it can be imported, for example `import <iostream>;`. Unlike a `#include`, preprocessing macros already defined at the point of the import do not affect how the header is processed. When that is inconvenient, for headers that use macros as configuration, a module unit can open with a global module fragment: the first declaration must be `module;`, only preprocessing directives may appear there, and a standard module declaration then ends the fragment and starts the module content.<sup>[1](https://en.cppreference.com/cpp/language/modules)</sup>

Header units have practical restrictions. In Clang, support for them, including the related command-line options, is explicitly experimental, and a header unit cannot be compiled to an object file because of its semantics; it can only be precompiled into a BMI. Clang also performs include translation, replacing `#include <iostream>` in a global module fragment with `import <iostream>;` when a BMI for the header is available.<sup>[2](https://clang.llvm.org/docs/StandardCPlusPlusModules.html)</sup> CMake's module support does not cover header units at all.<sup>[7](https://cmake.org/cmake/help/git-stage/manual/cmake-cxxmodules.7.html)</sup>

Header units are distinct from Clang's own header-modules extension, even though the two share implementation machinery. Clang modules can wrap multiple headers into one hierarchical module, semantics that Standard C++ header units do not have, and the Clang team chose not to reuse its `modulemap` format partly to avoid implying that those extra semantics are standard behavior.<sup>[2](https://clang.llvm.org/docs/StandardCPlusPlusModules.html)</sup>

## Build artifacts and toolchain support

Compiling a module interface unit produces a binary module interface alongside the object file. MSVC writes an `.ifc` file; Clang writes a `.pcm` file. These files are not portable: they depend on the compiler and the exact compilation flags used, so a library shipping modules must distribute its module source files (`.cppm`) and let users build the BMIs themselves, a job expected to fall to build systems.<sup>[5](https://learn.microsoft.com/en-us/cpp/build/compare-inclusion-methods?view=msvc-170)</sup><sup> • </sup><sup>[6](https://libcxx.llvm.org/Modules.html)</sup>

Because the compiler can resolve names before emitting the BMI, named modules are order-independent and macro-independent, and importing one loads a structured representation rather than re-running the preprocessor and front end over header text. Microsoft's guidance is to use named modules when C++20 features and the C++23 standard library are available, header units as an interim step when transitioning, and `#include` with precompiled headers otherwise.<sup>[5](https://learn.microsoft.com/en-us/cpp/build/compare-inclusion-methods?view=msvc-170)</sup>

Build-system support arrived gradually. CMake supports scanning sources for C++ modules with MSVC toolset 14.34 and newer, LLVM/Clang 16.0 and newer, and GCC 14 and newer, with `import std` support limited to newer toolchains such as Clang 18.1.2 and newer with libc++ or libstdc++, MSVC toolset 14.36 and newer, and GCC 15 and newer (GCC 16 on macOS).<sup>[7](https://cmake.org/cmake/help/git-stage/manual/cmake-cxxmodules.7.html)</sup> libc++ ships its `std` and `std.compat` module sources in `.cppm` files and describes its module support as experimental, with a temporary CMake project provided to help build the `.pcm` files.<sup>[6](https://libcxx.llvm.org/Modules.html)</sup>

## History

The design took roughly fifteen years. Daveed Vandevoorde sketched module ideas and syntax in paper N1736 in 2004; WG21 formed its Modules study group (SG2) in 2012, the year Doug Gregor reported on implementing modules in Clang; Gabriel Dos Reis and co-authors presented language wording for an implementation in 2014 (N4214); usable implementations appeared in Clang 5.0 and MSVC 19.1 in 2017; the Modules TS was finalized in 2018 (N4720); and Google proposed a competing design, the ATOM proposal (P0947), the same year. In 2019 the Modules TS and ATOM proposals merged as P1103, and the merged design entered the C++20 committee draft (N4810).<sup>[3](https://meetingcpp.com/mcpp/slides/2019/modules-the-beginners-guide-meetingcpp2019.pdf)</sup> The merged proposal made `export` and `module` real keywords rather than context-sensitive ones, and removed module ownership of entities declared inside `extern "C"` and `extern "C++"` blocks.<sup>[8](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1103r1.pdf)</sup>

## Adoption and measured effects

Converting existing code is nontrivial because the header model is embedded in how C++ libraries expose interfaces. A 2025 study converted the [deal.II](https://www.edgepedia.org/deal-ii) finite element library, about 800,000 lines of code, to C++20 modules using an approach that provides both header-based and module-based interfaces from the same code base. The conversion required a reliable configuration management system, build system, and compiler, and it reduced compile time for the converted library itself; for downstream projects, compile times showed no clear trend.<sup>[9](https://arxiv.org/abs/2506.21654)</sup>

Ecosystem adoption has lagged the language feature. A tracking report on the C++20 modules effort across compilers, build systems, and libraries noted that CMake 3.26, released in March 2023, experimentally supports building C++20 modules via the P1689R5 scanning protocol, which requires dedicated compiler support, and described available libraries as almost non-existent at that time.<sup>[10](https://github.com/royjacobson/modules-report)</sup>

## References

1. [Modules (since C++20), cppreference.com](https://en.cppreference.com/cpp/language/modules)
2. [Standard C++ Modules, Clang documentation](https://clang.llvm.org/docs/StandardCPlusPlusModules.html)
3. [Modules: The Beginner's Guide, Meeting C++ 2019 slides](https://meetingcpp.com/mcpp/slides/2019/modules-the-beginners-guide-meetingcpp2019.pdf)
4. [Overview of modules in C++, Microsoft Learn](https://learn.microsoft.com/en-us/cpp/cpp/modules-cpp)
5. [Compare header units, modules, and precompiled headers, Microsoft Learn](https://learn.microsoft.com/en-us/cpp/build/compare-inclusion-methods?view=msvc-170)
6. [Modules in libc++, libc++ documentation](https://libcxx.llvm.org/Modules.html)
7. [cmake-cxxmodules(7), CMake documentation](https://cmake.org/cmake/help/git-stage/manual/cmake-cxxmodules.7.html)
8. [P1103R1: Merging Modules, WG21](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1103r1.pdf)
9. [Experience converting a large mathematical software package written in C++ to C++20 modules, arXiv:2506.21654](https://arxiv.org/abs/2506.21654)
10. [modules-report: the state of C++20 modules across the ecosystem, GitHub](https://github.com/royjacobson/modules-report)

---
*Topic: Encyclopedia › Technology and the built world › Computing and digital systems › Software and programming › Programming languages › Programming language concepts*

*Initially written Sep 17, 2026 · Reviewed: Sep 30, 2026; Oct 15, 2026 · Edited: Sep 30, 2026; Oct 15, 2026 · Last review: Oct 15, 2026*

*Copyright 2026 EdgeChat AI, a subsidiary of Biostate AI.*

License: Edgepedia Community License 1.0, https://www.edgepedia.org/edgepedia/license
