C++20: Module Interface Unit and Module Implementation Unit


Thanks to the module interface unit and the module implementation unit, you can separate the interface from the implementation when defining a module. Let me show, how.


As promised in my last post C++20: A Simple math Modul, I want to make a short detour on my Clang Odyssee. My detour is a compact refresher to all I wrote in the referred post.

My Clang Odyssey

First, I don't want to blame anyone but me. Based on talks from Boris Kolpackov "Building C++ Modules" at the CppCon 2017 or Corentin Jabot "Modules are not a tooling opportunity" I had the impression, that the vendors suggested the following extensions for their module definition:

  • Windows: ixx
  • Clang: cppm
  • GCC: no suggestion

In the case of the Clang compiler, I was totally wrong. This is my simple math module, which I tried to compile with the Clang compiler.


// math.cppm

export module math;

export int add(int fir, int sec){
    return fir + sec;


I tried to compile the module with Clang 9 and Clang 10 on Microsoft and Linux. I tried to compile it with the brand-new Clang 11 compiler, built from the sources. Here is one of my many tries. 


This command-line should create the module math.pcm. I specified in the command-line -std=c++20 -fmodules-ts and the error message said: module interface compilation requires '-std=c++20' or '-fmodules-ts'.  I made all variations of the two flags, added the global module fragment to the module definition, invoked the Clang compiler with additional flags, but the result was always the same.

Then I asked Arthur O'Dwyer and Roland Bock for their help. For Arthur modules worked fine with Clang: "Hello World with C++2a modules". Roland rebuilt its Clang 11 and it worked with my module definition.

Roland and I  literally had the same Clang compiler and the same module definition. Character by character, I compared his command-line with mine, and I noticed something.

Mine:   clang++ -std=c++20 - -fmodules-ts -stdlib=libc++ -c math.cppm -Xclang -emit-module-interface -o math.pcm
Roland: clang++ -std=c++20 - -fmodules-ts -stdlib=libc++ -c math.cpp -Xclang -emit-module-interface -o math.pcm


Roland gave his module math.cpp cpp, and so did Arthur. Don't give your module definition the suffix cppm.

Now, compiling and using the module was straightforward.


To end this Odyssey here is the client.cpp file and a few words to the necessary flags for the Clang command line.


// client.cpp

import math;

int main() {
   add(2000, 20);


clang++ -std=c++2a -stdlib=libc++ -c math.cpp -Xclang -emit-module-interface -o math.pcm  // (1)
clang++ -std=c++2a -stdlib=libc++ -fprebuilt-module-path=. client.cpp math.pcm -o client   // (2)


  1. Creates the module math.pcm. The suffix pcm stands for precompiled module. The flag combination -Xclang -emit-module-interface is necessary for creating the precompiled module.
  2. Creates the executable client, which uses the module math.pcm. You have to specify the path to the module with the flag -fprebuilt-module-path.

The module math was straightforward. Let's be a bit more sophisticated.


Rainer D 6 P2 540x540Modernes C++ Mentoring

Stay informed about my mentoring programs. Subscribe for the news.



Guideline for a Module Structure

Here is the first guideline for a module structure:


module;                      // global module fragment

#include <headers for libraries not modularized so far>

export module math;          // module declartion 

import <importing of other modules> 

<non-exported declarations>  // names with only visibiliy inside the module

export namespace math {

    <exported declarations>  // exported names 



 This guideline serves two purposes. It gives you a simplified structure of a module and also an idea, what I'm going to write about. So, what's new in this module structure?

  • You can import modules. The imported modules have module linkage and are not visible outside the module. This observation also applies to the non-exported declarations.
  • I put the exported names in namespace math, which has the same name such as the module.
  • The module has only declared names. Let's write about the separation of the interface and the implementation of a module.

Module Interface Unit, and Module Implementation Unit

According to the previously mentioned guideline, I want to refactor the final version of module math from the previous post C++20: A Simple math Modul.

Module Interface Unit


// mathInterfaceUnit.ixx


import std.core;                            

export module math;       

export namespace math {

    int add(int fir, int sec);
    int getProduct(const std::vector<int>& vec);



  • The module interface unit contains the exporting module declaration: export module math.
  • The names add and getProduct are exported.
  • A module can have only one module interface unit.

Module Implementation Unit


// mathImplementationUnit.cpp

module math;

import std.core;

int add(int fir, int sec){
    return fir + sec;

int getProduct(const std::vector<int>& vec) {
    return std::accumulate(vec.begin(), vec.end(), 1, std::multiplies<int>());


  • The module implementation unit contains non-exporting module declarations: module math;
  • A module can have more than one module implementation unit.

Main Program


// client3.cpp

import std.core;

import math;

int main() {
    std::cout << std::endl;   
    std::cout << "math::add(2000, 20): " << math::add(2000, 20) << std::endl;
    std::vector<int> myVec{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    std::cout << "math::getProduct(myVec): " << math::getProduct(myVec) << std::endl;
    std::cout << std::endl;


  •  From the user's perspective, only the namespace math was added

Building the Executable

Manually building the executable includes a few steps.


cl.exe /std:c++latest /c /experimental:module mathInterfaceUnit.ixx /EHsc /MD      // (1)
cl.exe /std:c++latest /c /experimental:module mathImplementationUnit.cpp /EHsc /MD // (2)
cl.exe /std:c++latest /c /experimental:module client3.cpp /EHsc /MD                // (3)
cl.exe client3.obj mathInterfaceUnit.obj mathImplementationUnit.obj                // (4)


  1. Creates the object file mathInterfaceUnit.obj and the module interface file math.ifc.
  2. Creates the object file mathImplementationUnit.obj.
  3. Creates the object file client3.obj.
  4. Creates the executable client3.exe.

For the Microsoft compiler, you have to specify the exception handling model (/EHsc) and the multithreading library (/MD).  Additionally, use the flag /std:c++latest.

Finally, here is the output of the program:


What's next?

In the next post, I extend my module math with new features. First, I import modules and export them in one unit; second, I use names that are only visible inside the module.


Thanks a lot to my Patreon Supporters: Matt Braun, Roman Postanciuc, Tobias Zindl, Marko, G Prvulovic, Reinhold Dröge, Abernitzke, Frank Grimm, Sakib, Broeserl, António Pina, Sergey Agafyin, Андрей Бурмистров, Jake, GS, Lawton Shoemake, Animus24, Jozo Leko, John Breland, Venkat Nandam, Jose Francisco, Douglas Tinkham, Kuchlong Kuchlong, Robert Blanch, Truels Wissneth, Kris Kafka, Mario Luoni, Friedrich Huber, lennonli, Pramod Tikare Muralidhara, Peter Ware, Daniel Hufschläger, Alessandro Pezzato, Evangelos Denaxas, Bob Perry, Satish Vangipuram, Andi Ireland, Richard Ohnemus, Michael Dunsky, Leo Goodstadt, John Wiederhirn, Yacob Cohen-Arazi, Florian Tischler, Robin Furness, Michael Young, Holger Detering, Bernd Mühlhaus, Matthieu Bolt, Stephen Kelley, Kyle Dean, Tusar Palauri, Dmitry Farberov, Juan Dent, George Liao, Daniel Ceperley, Jon T Hess, Stephen Totten, Wolfgang Fütterer, Matthias Grün, and Phillip Diekmann.


Thanks in particular to Jon Hess, Lakshman, Christian Wittenhorst, Sherhy Pyton, Dendi Suhubdy, Sudhakar Belagurusamy, Richard Sargeant, Rusty Fleming, Ralf Abramowitsch, John Nebel, Mipko, and Alicja Kaminska.



My special thanks to Embarcadero CBUIDER STUDIO FINAL ICONS 1024 Small


My special thanks to PVS-Studio PVC Logo



I'm happy to give online seminars or face-to-face seminars worldwide. Please call me if you have any questions.

Bookable (Online)


Standard Seminars (English/German)

Here is a compilation of my standard seminars. These seminars are only meant to give you a first orientation.


Contact Me

Modernes C++,


Tags: modules, C++20


0 #1 Paul Topping 2020-09-17 17:22
In "Building the Executable", Step 1 compiles mathInterface.ixx but your description of it says it "Creates the object file mathInterfaceUnit.obj". Is this a typo? If not, where does "Unit" in the object file name come from?
0 #2 LP 2020-09-22 19:12
I've been using clang-10 since last fall, building modules with the .cppm suffix. Note that you need to omit the -fmodules-ts flag, as that causes clang to emulate an older modules implementation. You also need to use libc++, not libstdc++, anduse -std=c++2a (c++20 currently seems to ignore -fimplicit-modules). Oh, and the builtin module stuff means you need to use `import std;` rather than `import std.core` or similar.

Anyway, my complete clang command is

clang++ -stdlib=libc++ --std=c++2a -fbuiltin-module-map -fmodule-map-file=/usr/include/c++/v1/module.modul emap -fimplicit-modules -fPIC -fprebuilt-module-path=. --precompile -o math.pcm math.cppm
+1 #3 John McCabe 2021-02-12 20:57
This module stuff sounds a bit like what Ada had, with packages, in 1983, and Modula & Modula-2 had even before that. What an advanced language C++ is, to be introducing them nearly 40 years later!
0 #4 Alexander 2021-09-19 12:10
You always end the article with "in my next post". Could you perhaps add a link or a button which say "Next"? would be super helpful!
0 #5 Rainer 2021-09-20 17:17
Quoting Alexander:
You always end the article with "in my next post". Could you perhaps add a link or a button which say "Next"? would be super helpful!

Honestly, I did it with my first 100 posts but I ignored it with my last posts. I aske my daughter if she could do it.
+1 #6 Graham Asher 2022-02-05 09:41
Thanks for the article! Your frustration echoes mine. I recently experimented with modules and found that (after a struggle caused by my not understanding how modules worked, and my inability to follow the on-line documentation) I could get things working on VS2022, but when I tried to build the Linux version of my library using GCC 11, then Clang, I had to give up. GCC died with compiler errors and Clang refused to compile an open-source C library I use, although I think it was okay with my C++ module code.

A small style note on the function signature "export int add(int fir, int sec)". This is confusing. The words 'fir' and 'sec' both exist in English: fir is a tree and sec is an abbreviation for the unit of time. When abbreviating, it's best to go all the way or not at all: either

export int add(int a,int b)


export int add(int first, int second)

is preferable.

That makes code more readable. But the words 'first' and 'second' are not actually appropriate for a commutative function where the order of the operands does not matter, so 'a' and 'b' are better.
0 #7 Matthias 2022-08-18 19:14
Is the "import std.core;" required in both the Module Interface Unit and its Module Implementation Unit?
0 #8 Rainer Grimm 2022-09-07 12:12
Quoting Matthias:
Is the "import std.core;" required in both the Module Interface Unit and its Module Implementation Unit?

According to Microsoft, it's necessary in both.


Stay Informed about my Mentoring


English Books

Course: Modern C++ Concurrency in Practice

Course: C++ Standard Library including C++14 & C++17

Course: Embedded Programming with Modern C++

Course: Generic Programming (Templates)

Course: C++ Fundamentals for Professionals

Interactive Course: The All-in-One Guide to C++20

Subscribe to the newsletter (+ pdf bundle)

Blog archive

Source Code


Today 17

Yesterday 5583

Week 30526

Month 51273

All 10972734

Currently are 281 guests and no members online

Kubik-Rubik Joomla! Extensions

Latest comments