Hands on Modules in C++ 20

C++ 20 introduces modules, a feature that eliminates the problems introduced by traditional header files. The syntax of using a module: import , is quite similar to modern scripting languages like Python and JavaScript. I’m very curious about how import works under C++ and what changes does this new feature bring to modern C++. In this article, I’ll try a simple example with modules.


Here I’d recommend Clang 10. Just download the pre-built binaries and make sure you could use clang++ tools. If you’re a Windows user, enabling WSL2 would help setting up the compiler tools.

$ sudo apt install build-essential libncurses5$ bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)"

Once you’ve installed Clang 10, make sure it could be found in your path: which clang++

Hello Module!

/// helloworld.cpp
export module helloworld;
export auto hello() { return "Hello C++ 20!"; }

Then, let’s create our main.cpp , we can simply import the helloworld module we just created! By default, all the exported functions can be directly used once we import the module:

/// main.cpp
#include <iostream>
import helloworld;
int main() {
std::cout << hello() << std::endl;
return 0;

Now, let’s compile it. There are two steps in compiling this program:

  1. Compile the module into .pcm , which stands for Pre-compiled Module
  2. Compile main.cpp with the .pcm file

In Clang 10, we have to specify the flag -std=c++2a with other flags. Refer to the Clang Modules page for detailed explanation.

$ clang++ -std=c++2a -c helloworld.cpp -Xclang -emit-module-interface -o helloworld.pcm$ clang++ -std=c++2a -stdlib=libc++ -fprebuilt-module-path=. main.cpp helloworld.cpp

Run the compiled program, and we shall see the “Hello C++ 20!” output

$ ./a.out
Hello C++ 20!

Import Standard Library

// main.cpp
import <iostream>;
import helloworld;

To compile it, we have to add another two flags: -fimplicit-modules and -fimplicit-module-maps . Currently, Clang doesn’t support Semantic Import, which means you couldn’t do something like: import std.io (but MSVC supports). So we could compile the main.cpp like this:

$ clang++ -std=c++2a -stdlib=libc++ -fimplicit-modules -fimplicit-module-maps -fprebuilt-module-path=. main.cpp helloworld.cp

Use namespace in Module

/// helloworld.cpp
import <cstdio>;
export module helloworld;
export namespace helloworld {
int global_data;
void say_hello() {
std::printf("Hello Module! Data is %d\n", global_data);

Use helloworld namespace in main.cpp

/// main.cpp
import helloworld;
int main() {
helloworld::global_data = 123;

Here, we used import <cstdio> in our module, to successfully compile it, we need to specify -stdlib=libc++

$ clang++ -std=c++2a -stdlib=libc++ -fimplicit-modules -fimplicit-module-maps -c helloworld.cpp -Xclang -emit-module-interface -o helloworld.pcm
$ clang++ -std=c++2a -stdlib=libc++ -fimplicit-modules -fimplicit-module-maps -fprebuilt-module-path=. main.cpp helloworld.cpp
$ ./a.out
Hello Module! Data is 123

Good Practice of Module

#include <standard library header>
#include "library not ready for modularization"
export module top.middle.bottom;
import modularized.standard.library.component;
import other.modularized.library;
#include "module internal header" // beware!non-exported declarations;
export namespace top {
namespace middle {
namespace bottom {
exported declarations;


  • Module is still at very early stage for most compilers
  • Different compilers have their own implementation of modules. Not all the features of modules are supported yet

Such new features in C++ 20 will become popular someday when the standards, compilers, IDEs are ready for the new changes.

I think modules are fun to play with. Even though we won’t see modules being widely used this or next years, who knows if it will replace header files in five to ten years, right?

Fun fact: I first learnt about modules back in 2017, when Bjarne Stroustrup visited our school and gave a talk about it.

Graduate Student at Cornell University | Ex-Intern at Uber, Microsoft |Open Source Enthusiast | GitHub: mtobeiyf