More Details to Modules

 My last post gave you the introduction to modules in C++20. This post shows, how to use existing modules.

boxes 2624231 1280

Before I begin this post, let me shortly sum up, where we ended in my first post to modules.

A Short Recap

I created a module math1, which consisted of a module interface unit and a module implementation unit and a client, which used it. Here are the three source files.

Module Interface Unit

// math1.cppm

export module math1;

export int add(int fir, int sec);

Module Implementation Unit

// math1.cpp

module math1;

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

Client

// main1.cpp

import math1;

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

I compiled the program with a current clang and cl.exe compiler. From now on, I will stick with the cl.exe compiler because the compile line is a little bit shorter. As promised in my last post, let me show you the output of the program.

Using a Standard Module

Essential, neither the module interface unit nor the module implementation unit changed in the module math2.

Module Interface Unit

// math2.cppm

export module math2;

export int add(int fir, int sec);

Module Implementation Unit

// math2.cpp

module math2;

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

Client

// main2.cpp

//#include <iostream>

import std.core;

import math2;

int main(){
	
    std::cout << std::endl;
   
    std::cout << "add(2000, 20): " << add(2000, 20) << std::endl;
   
}

 

Thanks to the module std.core, I can show the result of the addition.

math2

Using the header <iostream> would also be possible. Of course, I hear your question, which modules are available. Here is what I have from 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 header <regex>
  • std.filesystem provides the content of header <experimental/filesystem>
  • std.memory provides the content of header <memory>
  • std.threading provodes the contents of headers <atomic>, <condition_variable>, <future>, <mutex>, <shared_mutex>, <thread>
  • std.core provides everything else in the C++ Standard Library

Modules provide a higher abstraction than headers. This makes it quite comfortable to use them. Additionally, you can specify, which name of a module should be exported or not.

Export versus Non-Export

The next module math3 is little more complicated as the previous one. Here is the interface.

Module Interface Unit

 

// math3.cppm

import std.core;

export module math3;

int add(int fir, int sec);

export int mult(int fir, int sec);

export void doTheMath();

 

The module interface unit contains the exporting module declaration: export module math3;. The module declaration starts the so-called module purview. Only names after the module purview, which are declared with export are exported. If not, the name is not visible outside the module and has, therefore, module linkage. This holds in particular for the function add but not for the functions mult and doTheMath.

Module Implementation Unit

// math3.cpp

module math3;

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

int mult(int fir, int sec){
    return fir * sec;
}

void doTheMath(){
	std::cout << "add(2000, 20): " << add(2000, 20) << std::endl;
}

 

There is nothing to add to the module implementation unit. The main program is more interesting.

Client

// main3.cpp

// #include <iostream>    // (1)
// #include <numeric>     // (1)
// #include <string>      // (1)
// #include <vector>      // (1)
import std.core;          // (2)

import math3;

int main(){
	
    std::cout << std::endl;
   
    // std::cout << "add(2000, 20): " << add(2000, 20) << std::endl;   // (3)
	
    std::vector<int> myVec = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
	
    std::string doc = "std::accumulate(myVec.begin(), myVec.end(), mult): "; 
    auto prod = std::accumulate(myVec.begin(), myVec.end(), 1, mult);
	
    std::cout << doc << prod << std::endl; 
	
    doTheMath();
	
}

 

You see, modules are quite comfortable in my case. Instead of using the four headers in the lines (1),  I'm okay with a simple import std.core in line (2). That was it. Here is the output of the program.

 math3

Now, to the question: What is happening if I use the function add in the line (3). To recap, add is not exported and has, therefore, module linkage. 

math3Add

The compiler complains that the function add is used in the main program, but the name add is not visible.

Further Details

First, you can export in various ways.

Export

Exporting names with export specifiers such as in math3.cppm is tedious.

Export Specifier

// math3.cppm

import std.core;

export module math3;

int add(int fir, int sec);

export int mult(int fir, int sec);

export void doTheMath()
 
Instead of an export specifier, you can use an exported group.

Exported Group

// math3.cppm

import std.core;

export module math3;

int add(int fir, int sec);

export {

int
mult(int fir, int sec); void doTheMath();

}
 
The third variation is it to use an exported namespace.

Exported Namespace

// math3.cppm

import std.core;

export module math3;

namespace math3 {

int add(int fir, int sec);

}

export namespace math3 {

int
mult(int fir, int sec); void doTheMath();

}
 
All three variations are semantically equivalent.
 

It may also be quite comfortable to re-export a module

Re-Export a Module

Sometimes, you want to export something which you imported from another module. If you don't export the imported module, the imported module has consequently module linkage and its names are not visible outside the module. Here is a concrete example.

Visible versus Invisible

Imagine, I want to import and use the module math.core and math.core2 in a new module math. Here are the module interface unit of math.core and math.core2.

  • Re-exported modules

 

// module interface unit of math.core

export math.core

export int mult(int fir, int sec); 

 

// module interface unit of math.core2

export math.core2

export int add(int fir, int sec); 

Next, here is the new module math.

  • The new module math

 

// module interface unit of math

export module math;

import math.core;           // not exported with mult
export import math.core2;   // exported with add


// module implementation unit of math

mult(1100, 2);             // fine
add(2000, 20);             // fine

As you can see, it's totally fine to use the exported and non-exported names in the module math. But the module math.core is not exported. Only a client, which uses the module math, will see the difference.

  • Client
// Client

import math

mult(1100, 2);             // ERROR
add(2000, 20);             // fine

The function mult has module linkage and is, therefore, not visible outside the module. Only the function add is visible.

Repackage Modules

There is a comfortable way to repackage modules. Just put them in an exported group.

export module math;

export{

    import math.core;
    import math.core2;
    import math.basics;
	
}

 

This makes all names visible for a client which import the module math.

What's next?

With my next post, I begin the last main topic of the C++ core guidelines: rules to the standard library. Believe it or not, many professional C++ developers don't use the standard template library (STL). This holds, in particular, true for the algorithms of the STL.

 

 

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, Darshan Mody, Sergey Agafyin, Андрей Бурмистров, Jake, GS, Lawton Shoemake, Animus24, Jozo Leko, John Breland, espkk, Wolfgang Gärtner,  Louis St-Amour, Stephan Roslen, Venkat Nandam, Jose Francisco, Douglas Tinkham, Kuchlong Kuchlong, Avi Kohn, Robert Blanch, Truels Wissneth, Kris Kafka, Mario Luoni, Neil Wang, Friedrich Huber, Sudhakar Balagurusamy, lennonli, and Pramod Tikare Muralidhara.

 

Thanks in particular to Jon Hess, Lakshman, Christian Wittenhorst, Sherhy Pyton, and Dendi Suhubdy

 

Seminars

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

Bookable (Online)

Deutsch

English

Standard Seminars 

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

New

Contact Me

Modernes C++,

RainerGrimmSmall

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 2626

Yesterday 7709

Week 26722

Month 185153

All 5054467

Currently are 156 guests and no members online

Kubik-Rubik Joomla! Extensions

Latest comments