In C++20, the concept of modules was introduced to improve the efficiency of the compilation process and provide better organization and encapsulation of code. Modules allow developers to divide their code into separate components, each with its own interface and implementation, and import them as needed. This article will explain the concept of modules in C++20, provide examples, and demonstrate the approach to working with modules.
Need for Modules
- Modules reduce the shortcomings associated with header files, thus compilation time is reduced.
- Module file is compiled once and the results are stored in a binary file which is processed by the compiler much faster than a header file.
- Macros and non-exported entities declared in a module are invisible outside the module.
- Modules can be imported in any order without taking care of macro redefinitions.
Module Units
A module unit is a source file meant to contain a module declaration. Different types of module units in C++20 modules are:
- Module interface unit: This unit exports a module name where the module declaration contains the export keyword.
- Module implementation unit: This unit is a separate file that is used to implement the modules.
- Module partition: It is a module where module-partition component is present.
Syntax
Module Declaration
To declare a module, you need to create a module interface unit, which is a separate file with the '.ixx', '.cppm', or '.mxx' extensions. Inside this file, you declare the module using the module keyword followed by the module name.
// module_name.ixx - Module interface unit
module module_name; // declares a module named "module_name"
export module module_name; // declares and exports a module named "module_name"
module A.B;
// declares a submodule named "B" within module "A"
export module A.B // declares and exports a submodule named "B" within module "A"
Exporting Declarations
Within a module, we can define declarations (e.g., variables, functions, classes) that we want to export to other modules using the 'export' keyword. Exported declarations become part of the module's interface and can be imported by other modules.
export module module_name; // module declaration
export data_type variable_name; // export declaration
export return_type function_name(); // export declaration
Example
cppm
// math.cppm - Module implementation file
// module declaration for math module
export module math;
// function to add two integers
export int add(int a, int b) { return a + b; }
// function to multiply two integers
export int multiply(int a, int b) { return a * b; }
Explanation
In the above example, we have a module named math implemented in the file 'math.cppm'. The export module math; statement declares the module named "math". The export keyword indicates that the module is part of the interface and can be imported by other modules.
Importing Modules and Declarations
To use declarations from other modules, we need to import them. The import keyword is used to import a module or a specific declaration from a module.
module module_name;
// imports the entire module "othermodule" into the current module "mymodule"
import othermodule;
// imports the declaration of the function "function_name" from the module "othermodule" into the current module "mymodule"
import othermodule.function_name;
Example
C++
// main.cpp
// importing the math module
import math;
#include <iostream>
int main()
{
// calling the add function from the math module
int result = add(3, 5);
// calling the multiply function from the math module
result = multiply(2, 4);
return 0;
}
Explanation
In the main.cpp file, we import the math module declared in the previous example using the import keyword. This allows us to access the functions add and multiply defined in the math module. We can use these functions as if they were defined in the current file.
Building and Compiling Modules
To compile and build modules, you'll need a C++20-compliant compiler. To compile and run the code, you'll need a C++20-compliant compiler that supports modules. The specific steps depend on the compiler you're using. Here's an example using 'g++' :
C
g++ -std=c++20 -c math.ixx // Compile the module interface unit
g++ -std=c++20 -c math_extra.cpp // Compile a partition (implementation unit)
g++ -std=c++20 main.cpp math.ixx math_extra.o -o main // Link the modules and build the executable
Output
Addition Result: 8
Multiplication Result:8
These are the basic syntax elements of modules in C++20. With modules, you can better organize and encapsulate your code, improve compilation times, and enhance code reusability and maintainability.
When a header file is included using the #include directive, the preprocessing macros defined within the translation unit can affect the processing of the included header file. However, when using modules, the processing of preprocessing macros defined within the translation unit does not directly affect the processing of included headers within the module. Here, the Global module fragment can be useful.
Global module fragment
A global module fragment can be placed at the beginning of module units. The global module fragment allows us to include header files when they can not be imported directly, particularly when the header file relies on preprocessing macros for configuration.
module;
// Preprocessing directives (optional)
module-declaration;
Example
cppm
// module_a_fragment.cppm (Global module fragment)
module;
// Preprocessing directives (optional)
#define MY_MACRO
// End of global module fragment
module A;
import<iostream>;
// Example function
export void demo_func() {
cout << "Hello from module A!\n";
}
C++
// main.cpp (not a module unit)
import A;
int main()
{
demo_func(); // Call function from module A
return 0;
}
Output
Hello from module A!
Private module fragment
Primary module interface unit can be suffixed by a private module fragment. Private module fragment represents a module as a single translation unit that restricts the accessibility of its contents to importers.
// Public declarations accessible to importers
module ModuleName;
// Private declarations not accessible to importers
module ModuleName : private;
// End of the private module fragment
Module partitions
A module can be divided in module partition units which starts with a colon :
. These partitions are only accessible by the main module.
export module A:B; // Declares a module interface unit for module 'A', partition ':B'.
Conclusion
This article demonstrates how to create and use modules in C++20. The module interface and implementation are separated, allowing for better organization and encapsulation of code. The imported module's functions can be used in other files, enhancing code reusability and maintainability.
Related Article:
Similar Reads
Modules in NestJS NestJS is a progressive Node.js framework that has gained significant popularity for building efficient, reliable, and scalable server-side applications. One of its core concepts is the use of modules, which help in organizing the application. In this article, weâll learn what modules are, why they
3 min read
Built-in Modules in Python Python is one of the most popular programming languages because of its vast collection of modules which make the work of developers easy and save time from writing the code for a particular task for their program. Python provides various types of modules which include Python built-in modules and ext
9 min read
Memory Model in C++ 11 Memory Model is a specification that describes how the program interacts with the memory. In C++ 11, a standardized memory model is created to provide the solution to issues surrounding concurrency, ordering, and multithreading. This framework specifies how memory is accessed and arranged in a C++ p
5 min read
std::source_location in C++ 20 The latest C++ standard version 20, brought about a fresh header file called <source_location> Header. It has an efficient method of obtaining details of a function or expression's source location while running. This functionality is immensely beneficial for debugging and profiling activities
3 min read
Features of C++ 20 C++ has a tradition of introducing new improvements and features in every 3 years in the form of a standard. With the last standard having released in 2017 as C++ 17, C++20 is going to be the latest standard. Below here are some major features in C++ 20: C++ Concepts library3-way comparisonsMap cont
8 min read
Perl | Modules A module in Perl is a collection of related subroutines and variables that perform a set of programming tasks. Perl Modules are reusable. Various Perl modules are available on the Comprehensive Perl Archive Network (CPAN). These modules cover a wide range of categories such as network, CGI, XML proc
3 min read
#include in C In C programming, the #include directive is very important to integrate any external files (header files) into a program, as the #include is used for file inclusion(a process of importing system-defined or user-defined files into the program). The #include is read by the preprocessor and instructs i
4 min read
C++ 20 - Feature Test Macros In C++, the stage is set for the entry of Feature Test Macros, a potent mechanism ushered in by C++20 to confront these compatibility quandaries head-on. Within this article, we shall embark on an exploration of Feature Test Macros, delve into their conceptual essence, grasp their significance, navi
5 min read
NodeJS Modules In NodeJS, modules play an important role in organizing, structuring, and reusing code efficiently. A module is a self-contained block of code that can be exported and imported into different parts of an application. This modular approach helps developers manage large projects, making them more scal
6 min read
__has_include in C++17 The __has_include is a special operator to work with preprocessor directives that allow you to check if a particular header file is available for inclusion in your program. It is a conditional compilation feature introduced in C++17 that helps you write portable code that can handle different enviro
2 min read