Skip to main content

Section 6.5 Modules

The C++20 standard introduced a new way to break code into multiple filesβ€”modules . A module is written in a single file instead of a .h/.cpp pair. When a compiler builds a module, it creates the object code like normal, but it also automatically creates a file that works like a .h to declare what is in the file. When we make use of the module in other files, the compiler automatically finds and reads that file to discover what is available.

Insight 6.5.1.

You can think of a module as a .cpp file that (among other things) will automatically generate its own .h file
To create a module, we need two new keywords. The module keyword is used to declare that we are starting a module. Within a module, export is used to state what code in the module is made available to use outside of the module. In a simple library, we may export everything. But in a more complex code base, there may be helper functions that are needed in the module that do not make sense to use outside of the module. In that case, we would not export those functions.
Here is a module file library.cxx that would work just like our library.h/library.cpp pair:

Note 6.5.2.

A module file can have any extension (like .cxx) we choose. But it is common to use something other than .cpp to indicate that the file is a C++ module. .cxx is one common extension used for this purpose.
It is possible to write a module that spans multiple files, we will keep things simple by placing each module in a single file.
Listing 6.5.1. library.cxx
// Start global module fragment
module;

// All includes go here
#include <cmath>

// Start module, declare its name and make available outside this module
export module library;

// Using namespace is safer in a module as it will be scoped to this module only
// The place to do so is after the module declaration
using namespace std;

// Declare the functions in the module. Only the functions marked with `export`
// will be available outside this module.

/**
 * @brief Gets the number 2. A silly function that demonstrates a function
 * that is NOT exported
 * 
 * @return 2
 */
int getMultiplier() {
    return 2;
}

/**
 * @brief Doubles the value of the input number
 * This function is exported for use outside this module.
 * 
 * @param num an integer value
 * @return int 2x the input number
 */
export int doubleValue(int num) {
    int result = getMultiplier() * num;
    return result;
}
Key things to note:
  • Line 2 uses module; to declare that this is a module and begin the β€œglobal module fragment”. Any includes (uses of non-module libraries) need to be in this part of the file. If there are no includes needed in a file, this part can be skipped. (We could remove the <cmath include and then remove everything before line 8.)
  • Line 8 does three things:
    • It starts this module
    • It gives the module the name library
    • The word export makes library available outside of the module.
  • Line 30 uses export to state that the doubleValue function will also be available outside of the module.
To use a module in another file, we need to import the module (not include it):
Listing 6.5.2. main.cpp (with module import)
Figure 6.5.3. Compiling main.cpp and the module library.cxx. Compiling the library automatically generates the necessary interface file that will be used when main.cpp imports the module.

Warning 6.5.3.

Modules are relatively new, and not completely supported by all compilers. You may need to use a specific version of the compiler or enable a special flag to use modules. For example, when using the g++ compiler, you need to use the -fmodules-ts flag to enable modules and ensure that the compiler is using C++20 (or above) features with -std=c++20.
To build the code above using g++, we need the recipe:
$ g++ -std=c++20 -fmodules-ts library.cxx main.cpp -o program.exe

Note 6.5.4.

Although support for modules is still evolving, they offer a simpler mechanism for organizing code than the traditional header/source file pairs. In addition, the module system of importing/exporting specific functions is closer to how other programming languages, such as Python and Javascript, handle code organization.
You should be familiar with both headers and modules, but in this book, we will primarily use modules when we need to simulate multiple files.

Checkpoint 6.5.1.

Write a module file mycode.cxx for a library that just has a void function called print that takes a string parameter. You will not use all of the blocks.
You have attempted of activities on this page.