Expert C++
上QQ阅读APP看书,第一时间看更新

Using modules in C++20

Modules fix header files with annoying include-guard issues. We can now get rid of preprocessor macros. Modules incorporate two keywords, import and export. To use a module, we import it. To declare a module with its exported properties, we use export. Before listing the benefits of using modules, let's look at a simple usage example. The following code declares a module:

export module test;

export int twice(int a) { return a * a; }

The first line declares the module named test. Next, we declared the twice() function and set it to export. This means that we can have functions and other entities that are not exported, thus, they will be private outside of the module. By exporting an entity, we set it public to module users. To use module, we import it as done in the following code:

import test;

int main()
{
twice(21);
}

Modules are a long-awaited feature of C++ that provides better performance in terms of compilation and maintenance. The following features make modules better in the competition with regular header files:

  • A module is imported only once, similar to precompiled headers supported by custom language implementations. This reduces the compile time drastically. Non-exported entities have no effect on the translation unit that imports the module. 
  • Modules allow expressing the logical structure of code by allowing you to select which units should be exported and which should not. Modules can be bundled together into bigger modules.
  • Getting rid of workarounds such as include-guards, described earlier. We can import modules in any order. There are no more concerns for macro redefinitions.

Modules can be used together with header files. We can both import and include headers in the same file, as demonstrated in the following example:

import <iostream>;
#include <vector>

int main()
{
std::vector<int> vec{1, 2, 3};
for (int elem : vec) std::cout << elem;
}

When creating modules, you are free to export entities in the interface file of the module and move the implementations to other files. The logic is the same as in managing .h and .cpp files.