C++20: A Simple math Module

Contents[Show]

Modules are one of the four prominent features of C++20. They overcome the restrictions of header files and promise a lot: faster build-times, fewer violations of the One-Definition-Rule, less usage of the preprocessor. Today, I want to create a simple math module.

 

 TimelineCpp20

The Long History of Modules in C++

wg21 structure 2019 11

Modules may be older than you think. My short historic detour should give only an idea, how long it takes to get something such valuable into the C++ standard.

In 2004, Daveed Vandevoorde wrote the proposal N1736.pdf, which described the first time the idea of modules. It took until 2012 to get a dedicated Study Group (SG2, Modules) for modules. In 2017, Clang 5.0 and MSVC 19.1 provided the first implementation. One year later, the Modules TS (technical specification) was finalized. Around the same time, Google proposed the so-called ATOM (Another Take On Modules) proposal (P0947) for modules. In 2019, the Modules TS and the ATOM proposal was merged into the C++20 committee draft (N4842), which is the syntax I present in my posts to modules.

The C++ standardization process is democratic. Section Standardization gives you more information about the standard and the standardization process. The image to the right shows the various study groups.

 

 

 

 

Explaining modules for the user's perspective is quite easy, but this will not hold for the implementer's perspective. My plan for this post is to start with a simple modules math and add more features to it as we go.

The math Modul

First, here is my first module:

// math.ixx

export module math;

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

The expression export module math is the module declaration. By putting export before the function add, add is exported and can, therefore, be used by a consumer of my module. 

 

// client.cpp

import math;

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

import math imports the module math and makes the exported names in the module visible to the client.cpp. Let me say a few words about module declaration files before I build the module.

Module Declaration Files

Did you noticed the strange name of the module: math.ixx.

  • cl.exe (Microsoft) uses the required extension ixx. The ixx stands for a module interface source.
  • Clang uses the extensioncppm. cppm stands presumably for a cpp module declaration. Wrong!!! The documentation to Clang is misleading. Stop using the cppm extension until you read my next post. Use the extension cpp. I assume you don't want to make the same Odyssey such as me.  
  • I don't know of a GCC extension.

Compile the Module math

To compile the module, you have to use a very current Clang, GCC, or cl.exe compiler. I go in this post with cl.exe on Windows. The Microsoft blog provides two excellent introductions to modules: Overview of modules in C++ and C++ Modules conformance improvements with MSVC in Visual Studio 2019 16.5. In contrast, the lack of introductions to the Clang and GCC compiler makes it quite difficult to use modules.

Here are more details to my used Microsoft compiler:

 MicrosoftCompiler

 

These are the steps to compile and use the module with the Microsoft compiler. I only show the minimal command line. With an older Microsoft compiler, you have to use at least /std:cpplatest.

 

cl.exe /experimental:module /c math.ixx           // 1
cl.exe /experimental:module client.cpp math.obj   // 2                            

 

  1. Creates an obj file math.obj and an IFC file math.ifc. The IFC file contains the metadata description of the module interface. The binary format of the IFC is modeled after the Internal Program Representation by Gabriel Dos Reis and Bjarne Stroustrup (2004/2005). 
  2. Creates the executable client.exe. Without the implicitly used math.ifc file from the first step, the linker can not find the module.

moduleNotFound1

For obvious reasons, I will not show you the output of the program execution. Let me change this.

Global Module Fragment

The global module fragment is meant to compose module interfaces. It's a place to use preprocessor directives such as #include so that the module interface can compile. The code in the global module fragment is not exported by the module interface.

The second version of the module math supports the two functions add and getProduct.

 

// math1.ixx
module;                   // global module fragment (1)

#include <numeric>
#include <vector>

export module math;       // module declartion (2)

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

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

 

I included the necessary headers between the global module fragment (line 1) and the module declaration (line 2).

 

// client1.cpp

#include <iostream>
#include <vector>

import math;

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

 

 The client imports the module math and uses its functionality:

client1

Maybe, you don't like to use a Standard Library Header anymore. Microsoft supports modules for all STL headers. Here is what I have found in the post "Using C++ Modules in Visual Studio 2017" from the Microsoft C++ team blog.

  • C++ modules in Visual Studio 2017
    • std.regex provides the content of the header <regex>
    • std.filesystem provides the content of the header <experimental/filesystem>
    • std.memory provides the content of the header <memory>
    • std.threading provides the contents of headers <atomic>, <condition_variable>, <future>, <mutex>, <shared_mutex>,and <thread>
    • std.core provides everything else in the C++ Standard Library

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

Here are the modified versions of the interface file math2.ixx and the source file client2.cpp.

  • math2.ixx
// math2.ixx
module;                   

import std.core;                            // (1)

export module math;       

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

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

  • client2.cpp
// client2.cpp

import std.core;                  // (1)

import math;

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

 

Both files use in line (1) the module std.core.

What's next?

My first modules math.ixx, math1.ixx, and math2.ixx defined its functionality in one file. In the next post, I separate the module definition in a so-called module interface unit and a so-called module implementation unit. 

 

 

Thanks a lot to my Patreon Supporters: Meeting C++, Matt Braun, Roman Postanciuc, Venkata Ramesh Gudpati, Tobias Zindl, Marko, G Prvulovic, Reinhold Dröge, Abernitzke, Richard Ohnemus, Frank Grimm, Sakib, Broeserl, António Pina, Markus Falkner, Darshan Mody, Sergey Agafyin, Андрей Бурмистров, Jake, GS, Lawton Shoemake, Animus24, Jozo Leko, John Breland, espkk, Wolfgang Gärtner, Jon Hess, Christian Wittenhorst, Louis St-Amour, Stephan Roslen, Venkat Nandam, and Jose Francisco.

 

Thanks in particular to: Bitwyre Technologies

 

Thanks in particular to:   crp4

 

   

Get your e-book at Leanpub:

The C++ Standard Library

 

Concurrency With Modern C++

 

Get Both as one Bundle

cover   ConcurrencyCoverFrame   bundle
With C++11, C++14, and C++17 we got a lot of new C++ libraries. In addition, the existing ones are greatly improved. The key idea of my book is to give you the necessary information to the current C++ libraries in about 200 pages. I also included more than 120 source files.  

C++11 is the first C++ standard that deals with concurrency. The story goes on with C++17 and will continue with C++20.

I'll give you a detailed insight into the current and upcoming concurrency in C++. This insight includes the theory and a lot of practice with more than 140 source files.

 

Get my books "The C++ Standard Library" (including C++17) and "Concurrency with Modern C++" in a bundle.

In sum, you get more than 700 pages full of modern C++ and more than 260 source files presenting the standard library and concurrency in practice.

 
Tags: modules

My Newest E-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

Subscribe to the newsletter (+ pdf bundle)

Blog archive

Source Code

Visitors

Today 548

All 4165839

Currently are 121 guests and no members online

Kubik-Rubik Joomla! Extensions

Latest comments