In the last weeks, I learned something new about modules in C++20: private modules fragments and header units. Consequently, I make a short detour in this post and present these new features.
You may wonder why I didn’t complete my promised post about variadic templates. The reason is simple. The next pdf-bundle I publish next week is about C++20 modules, and I want to incorporate this post in this bundle. Before I do that, I have to write this post.
Private module fragments and header units make dealing with modules in C++20 way more comfortable.
I intentionally use the newest Visual Studio compiler in this post because its C++20 modules support is almost complete. The newest GCC and Clang only partially support modules.
private Module Fragment
I’m unsure if you have the facts about the module interface unit and implementation unit ready. Therefore, let me repeat the essential facts.
When you want to separate your module into an interface and an implementation, you should structure it into a module interface unit and one or more module implementation units.
Module Interface Unit
- 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
- The module implementation unit contains non-exporting module declarations: module math;
- A module can have more than one module implementation unit.
- From the user’s perspective, only the namespace math was added.
Building the Executable
Manually building the executable includes a few steps.
- Creates the object file mathInterfaceUnit2.obj and the module interface file math.ifc.
- Creates the object file mathImplementationUnit2.obj.
- Creates the object file client4.obj.
- Creates the executable client4.exe.
You should specify the exception handling model (/EHsc) for the Microsoft compiler. Additionally, use the flag /std:c++latest.
Finally, here is the output of the program:
One of the significant advantages of structuring modules into a module interface unit and one or more module implementation units is that modifications in the module implementation units do not affect the module interface unit and, therefore, require no recompilation.
Private Module Fragment
Thanks to a private module fragment, you can implement a module in one file and declare its last part as its implementation using
module :private;. Consequently, a modification of the private module fragment does not cause recompilation. The following module declaration file
mathInterfaceUnit3.ixx refactors the module interface unit
mathInterfaceUnit2.ixx and the module implementation unit
mathImplementationUnit2.cpp into one file.
module: private; (line 1) denotes the start of the
private module fragment. A modification in this optional last part of a module declaration file does not cause its recompilation.
I already presented header units in a previous post. Now, I can use them
Header units are a smooth way to transition from headers to modules. You have to replace the
#include directive with the new
First, import respects the same lookup rules as include. This means in the case of the quotes (“myHeader.h”), the lookup first searches in the local directory before it continues with the system search path.
Second, this is way more than text replacement. In this case, the compiler generates something module-like from the import directive and treats the result as a module. The importing module statement gets all exportable names for the header. The exportable names include macros. Importing these synthesized header units is faster and comparable in speed to precompiled headers.
Modules are not Precompiled Header
Precompiled headers are a non-standardized way to compile headers in an intermediate form that is faster to process for the compiler. The Microsoft compiler uses the extension
.pch , and the GCC compiler
.gch for precompiled headers. The main difference between precompiled headers and modules is that modules can selectively export names. Only in a module are exported names visible outside the module.
After this short remainder, let me try it out.
Use of Header Units
The following example consists of three files. The header file
head.h, declaring the function
hello, its implementation file
head.cpp, defining the function
hello, and the client file
helloWorld3.cpp using the function
Only the implementation file
head.cpp and the client file
helloWorld3.cpp are special. They import the header file
head.h: import "head.h";.
These are the necessary step to use header units.
- The flag
/exportHeader(first line) causes the creation of the ifc file
head.h.ifcfrom the header file
head.h. The ifc file contains the metadata description of the module interface.
- The implementation file
head.cpp(second line) and the client file
helloWordl3.cpp(third line) use the header unit. The flag
/headerUnit head.h=head.h.ifcimports the header and tells the compiler or linker the name of the ifc file for the specified header.
In my next post, I will use variadic templates to implement the C++ idiom for a fully generic factory. One implementation of this life-saving C++ idiom is
Thanks a lot to my Patreon Supporters: Matt Braun, Roman Postanciuc, Tobias Zindl, G Prvulovic, Reinhold Dröge, Abernitzke, Frank Grimm, Sakib, Broeserl, António Pina, Sergey Agafyin, Андрей Бурмистров, Jake, GS, Lawton Shoemake, 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, 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, Phillip Diekmann, Ben Atakora, Ann Shatoff, Rob North, Bhavith C Achar, and Marco Parri Empoli.
Thanks, in particular, to Jon Hess, Lakshman, Christian Wittenhorst, Sherhy Pyton, Dendi Suhubdy, Sudhakar Belagurusamy, Richard Sargeant, Rusty Fleming, John Nebel, Mipko, Alicja Kaminska, Slavko Radman, and David Poole.
|My special thanks to Embarcadero|
|My special thanks to PVS-Studio|
|My special thanks to Tipi.build|
|My special thanks to Take Up Code|
I’m happy to give online seminars or face-to-face seminars worldwide. Please call me if you have any questions.
- Embedded Programmierung mit modernem C++ 12.12.2023 – 14.12.2023 (Präsenzschulung, Termingarantie)
Standard Seminars (English/German)
Here is a compilation of my standard seminars. These seminars are only meant to give you a first orientation.
- C++ – The Core Language
- C++ – The Standard Library
- C++ – Compact
- C++11 and C++14
- Concurrency with Modern C++
- Design Pattern and Architectural Pattern with C++
- Embedded Programming with Modern C++
- Generic Programming (Templates) with C++
- Clean Code with Modern C++
- Phone: +49 7472 917441
- Mobil:: +49 176 5506 5086
- Mail: schulung@ModernesCpp.de
- German Seminar Page: www.ModernesCpp.de
- Mentoring Page: www.ModernesCpp.org
Modernes C++ Mentoring,