Modules in C++ are a feature added in C++20 implementing modular programming as a modern alternative to precompiled headers. A module in C++ comprises a single translation unit. Like header files and implementation files, a module can contain declarations and definitions, but differ from precompiled headers in that they do not require the preprocessor directive #include, but rather are accessed using the keyword import. A module must be declared using the keyword module to indicate that the translation unit is a module. A module, once compiled, is stored as a built module interface (BMI) file which behaves similarly to a (precompiled header) file. Module symbols and imports are resolved at the compilation stage, not the linking stage.

Modules most commonly have the extension (primarily common within Clang and GCC toolchains), though some alternative extensions include and (more common in Microsoft/MSVC toolchains), or even the traditional C++ extension .

Though the standard C language does not have modules, dialects of C allow for modules, such as Clang C. However, the syntax and semantics of Clang C modules differ from C++ modules significantly.

History Prior to the conception of modules, C++ relied on the system of headers and source files. Precompiled headers existed and were similar to modules as snapshots of translation units easier to parse by the compiler and thus providing faster compilation, but did not have the same laws of encapsulation as modules. Modules were first proposed in 2012 for inclusion to C++14, but underwent extensive revisions and an entire redesign until the modern form was merged into C++20.

Main uses Modules provide the benefits of precompiled headers with faster compilation than #included traditional headers, as well as faster processing during the linking phase. This is because modules are not handled by the C preprocessor during the preprocessing step, but rather directly by the compiler during compilation. Modules also reduce boilerplate by allowing code to be implemented in a single file, rather than being separated across a header file and source implementation. Separation of "interface file" and "implementation file" is still possible with modules, though modules provide a cleaner encapsulation of code. Separating code interface and source implementation, however, is necessary for benefiting from incremental builds. Modules eliminate the necessity of guards or , as modules do not directly modify the source code. Modules, unlike headers, do not have to be processed or recompiled multiple times. However, similar to headers, any change in a module necessitates the recompilation of not only the module itself but also all its dependencies, and the dependencies of those dependencies, et cetera. Like headers, modules do not permit circular dependencies, and will not compile.ISO/IEC 14882:2020. Programming Languages – C++ (3rd ed.). International Organization for Standardization. §9.3, "Module interface units and import/export rules," and §16.3, "Module dependencies."

Currently, built module interface (BMI) files differ between compilers and are not portable, and highly dependent on exact compiler version, target architecture, and compilation flags (thus are considered more like temporary build artefacts rather than shippable binaries). For example, of the BMIs of the major C++ compilers: GCC uses (GCC compiled module) Clang uses (precompiled module) MSVC uses (interface file container)

A module is imported using the keyword import followed by a module name, while a module is declared with export module followed by the name. An import statement indicates to the compiler to load the built module interface (BMI) file of the module to resolve used symbols. All symbols within a module meant to be publicly exposed are marked export, and importing the module exposes all exported symbols to the translation unit. If a module is never imported, it will never be loaded.ISO/IEC 14882:2020. Programming Languages – C++ (3rd ed.). International Organization for Standardization. §9.3, "Module interface units and import/export rules," and §16.2, "Module import semantics." Modules can export named symbols, but not macros which are consumed before compilation. Thus, modules prevent unwanted leakage of macros across translation units.

Unlike header inclusions, the order of import statements do not matter. A module can allow for transitive imports by marking an import with export import, which re-exports the imported module to a translation unit that imports the first module. Modules do not enforce any notion of namespaces, though by convention, modules should match namespaces and source file paths (for example, a namespaced class like wikipedia::project::util::ConfigLoader declared in module wikipedia.project.util.ConfigLoader residing in file , similar to Java convention). using statements will only be applied in translation units if explicitly marked export, making it much less likely that using a using statement to bring symbols into the global namespace will cause name clashes across module translation units. This resolves pollution of using statements in headers, which due to textual inclusion of the header by an #include directive, will always result in using statements adding symbols into scope, even if unintentional.

The keyword export was first introduced in C++03 when "exported templates" were added to C++. These were later removed in C++11, due to very few compilers actually supporting the feature. The only compiler known to support exported templates was Comeau C/C++.

Standard library modules

C++20 specifies the introduction of C++ Standard Library header units, and C++23 adds full module support for the standard library (however modules are informally available in most C++20 implementations). At present, through modules, the standard library must be imported in its entirety (using import std;). The C++ standards offer two standard library modules: Name Description Exports all declarations in namespace std and global storage allocation and deallocation functions that are provided by the importable C++ library headers including C library facilities (although declared in standard namespace). Exports the same declarations as the named module std, and additionally exports functions in global namespace in C library facilities. It thus contains "compat" in the name, meaning compatibility with C.

The module names std and std.* are reserved by the C++ standard, and thus declaring a module whose name matches either pattern will issue a compiler warning. However, most compilers provide a flag to bypass or suppress that warning (for example -Wno-reserved-module-identifier in Clang and GCC).

Tooling support Currently, only GCC, Clang, and MSVC offer support for modules and import std;. The Clangd language server supports modules.

Build system support varies. CMake, MSBuild, XMake, Meson, and Build2 provide full support for modules. Generated build systems such as Make and Ninja also have support for modules. However, Gradle for C++ and Bazel do not yet support modules. Qt moc does not recognise modules in its preprocessor currently.

Example A simple example of using modules is as follows:

export module wikipedia.project.Person;

import std;

using std::string;

export namespace wikipedia::project {

class Person { private: string name; int age; public: Person(string name, int age): name{std::move(name)}, age{age} {}

string getName() const { return name;

void setName(string name) { this->name = std::move(name);

int getAge() const noexcept { return age;

void setAge(int age) noexcept { this->age = age;

import std;

import wikipedia.project.Person;

using wikipedia::project::Person;

int main(int argc, char* argv[]) { Person me("John Doe", 10); me.setAge(15); std::println("Hello, {0}! {0} is {1} years old.", me.getName(), me.getAge()); // prints "Hello, John Doe! John Doe is 15 years old." }

Header units Headers may also be imported, even if they are not declared as modules. Imported headers are called "header units", and are designed to allow existing codebases to migrate from headers to modules more gradually. The syntax is similar to including a header, with the difference being that #include is replaced with import. As import statements are not preprocessor directives but rather statements of the language read by the compiler, they must be terminated by a semicolon. Header units automatically export all symbols, and differ from proper modules in that they allow the emittance of macros, meaning all translation units that import the header unit will obtain its contained macros. This offers minimal breakage between migration to modules. The semantics of searching for the file depending on whether quotation marks or angle brackets are used apply here as well. For instance, one may write import <string>; to import the <string> header, or import "MyHeader.h"; to import the file "MyHeader.h" as a header unit. Most build systems, such as CMake, have only experimental support for this.

Similar to Go import statements, header unit imports are followed by a raw string literal representation of the path. However, one cannot write a compile-time string literal and import that expecting it to be interpreted as a path.

Anatomy

Module partitions and hierarchy Modules may have partitions, which separate the implementation of the module across several files. Module partitions are declared using the syntax A:B, meaning the module A has the partition B. Module partitions cannot individually be imported outside of the module that owns the partition itself, meaning that any translation unit that requires code located in a module partition must import the entire module that owns the partition.

The module partition B is linked back to the owning module A with the statement import :B; in the file containing the declaration of module A or any other module partition of A (say A:C), which implicitly resolves :B to A:B, because the module is named A. These import statements may themselves be exported by the owning module, even if the partition itself cannot be imported directly, and thus importing code from a partition is done by just importing the entire module.

If a module is split between module interface and module implementation, its translation unit consists of both the interface and implementation. Similarly, if a module has partitions, its translation unit encompasses all of those modules as well.

Other than partitions, modules do not have a hierarchical system or "submodules", but typically use a hierarchical naming convention, similar to Java's packages. Only alphanumeric characters, the underscore, and the period may appear in the name of a module.ISO/IEC 14882:2020. Programming Languages – C++ (3rd ed.). International Organization for Standardization. §9.2, "Module interface units and import/export rules." In C++, the name of a module is not tied to the name of its file or the module's location, unlike in Java, and the package it belongs to must match the path it is located in. For example, the modules A and A.B in theory are disjoint modules and need not necessarily have any relation, however employing such a naming scheme with periods in the module name is used to suggest that the module A.B is related or otherwise associated with the module A.