Skip to content

Repo sync for protected branch #4920

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 32 additions & 24 deletions docs/cpp/modules-cpp.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
---
title: "Overview of modules in C++"
ms.date: 04/24/2023
ms.date: 01/29/2024
helpviewer_keywords: ["modules [C++]", "modules [C++], overview"]
description: Modules in C++20 provide a modern alternative to header files.
---
# Overview of modules in C++

C++20 introduces *modules*, a modern solution that turns C++ libraries and programs into components. A *module* is a set of source code files that are compiled independently of the source files (or more precisely, the [translation units](https://wikipedia.org/wiki/Translation_unit_(programming)) that import them). Modules eliminate or reduce many of the problems associated with the use of header files. They often reduce compilation times. Macros, preprocessor directives, and nonexported names declared in a module aren't visible outside the module. They have no effect on the compilation of the translation unit that imports the module. You can import modules in any order without concern for macro redefinitions. Declarations in the importing translation unit don't participate in overload resolution or name lookup in the imported module. After a module is compiled once, the results are stored in a binary file that describes all the exported types, functions, and templates. The compiler can process that file much faster than a header file. And, the compiler can reuse it every place where the module is imported in a project.
C++20 introduces *modules*. A *module* is a set of source code files that are compiled independently of the source files (or more precisely, the [translation units](https://wikipedia.org/wiki/Translation_unit_(programming)) that import them.

Modules eliminate or reduce many of the problems associated with the use of header files. They often reduce compilation times, sometimes significantly. Macros, preprocessor directives, and nonexported names declared in a module aren't visible outside the module. They have no effect on the compilation of the translation unit that imports the module. You can import modules in any order without concern for macro redefinitions. Declarations in the importing translation unit don't participate in overload resolution or name lookup in the imported module. After a module is compiled once, the results are stored in a binary file that describes all the exported types, functions, and templates. The compiler can process that file much faster than a header file. And, the compiler can reuse it every place where the module is imported in a project.

You can use modules side by side with header files. A C++ source file can `import` modules and also `#include` header files. In some cases, you can import a header file as a module, which is faster than using `#include` to process it with the preprocessor. We recommend that you use modules in new projects rather than header files as much as possible. For larger existing projects under active development, experiment with converting legacy headers to modules. Base your adoption on whether you get a meaningful reduction in compilation times.

Expand Down Expand Up @@ -43,11 +45,13 @@ import std.core;
import std.regex;
```

To consume the Microsoft Standard Library modules, compile your program with [`/EHsc`](../build/reference/eh-exception-handling-model.md) and [`/MD`](../build/reference/md-mt-ld-use-run-time-library.md) options.
To consume the Microsoft Standard Library modules, compile your program with the [`/EHsc`](../build/reference/eh-exception-handling-model.md) and [`/MD`](../build/reference/md-mt-ld-use-run-time-library.md) options.

## Example

The following example shows a simple module definition in a source file called *`Example.ixx`*. The *`.ixx`* extension is required for module interface files in Visual Studio. In this example, the interface file contains both the function definition and the declaration. However, you can also place the definitions in one or more separate module implementation files, as shown in a later example. The `export module Example;` statement indicates that this file is the primary interface for a module called `Example`. The **`export`** modifier on `f()` indicates that this function is visible when another program or module imports `Example`. The module references a namespace `Example_NS`.
The following example shows a simple module definition in a source file called *`Example.ixx`*. The *`.ixx`* extension is required for module interface files in Visual Studio. In this example, the interface file contains both the function definition and the declaration. However, you can also place the definitions in one or more separate module implementation files, as shown in a later example.

The `export module Example;` statement indicates that this file is the primary interface for a module called `Example`. The **`export`** modifier on `f()` indicates that this function is visible when another program or module imports `Example`.

```cpp
// Example.ixx
Expand All @@ -67,7 +71,7 @@ namespace Example_NS
}
```

The file *`MyProgram.cpp`* uses the **`import`** declaration to access the name that is exported by `Example`. The name `Example_NS` is visible here, but not all of its members. Also, the macro `ANSWER` isn't visible.
The file *`MyProgram.cpp`* uses **`import`** to access the name exported by `Example`. The namespace name `Example_NS` is visible here, but not all of its members because they aren't exported. Also, the macro `ANSWER` isn't visible because macros aren't exported.

```cpp
// MyProgram.cpp
Expand Down Expand Up @@ -109,64 +113,68 @@ The `import` declaration can appear only at global scope.

## Implementing modules

A *module interface* exports the module name and all the namespaces, types, functions, and so on, that make up the public interface of the module. A *module implementation* defines the things exported by the module. In its simplest form, a module can consist of a single file that combines the module interface and implementation. You can also put the implementation in one or more separate module implementation files, similar to how *`.h`* and *`.cpp`* files do it.
A *module interface* exports the module name and all the namespaces, types, functions, and so on, that make up the public interface of the module.\
A *module implementation* defines the things exported by the module.\
In its simplest form, a module can be a single file that combines the module interface and implementation. You can also put the implementation in one or more separate module implementation files, similar to how *`.h`* and *`.cpp`* files do it.

For larger modules, you can split parts of the module into submodules called *partitions*. Each partition consists of a module interface file that exports a module partition name. A partition may also have one or more partition implementation files. The module as a whole has one *primary module interface*, which is the public interface of the module and may export the partition interfaces.
For larger modules, you can split parts of the module into submodules called *partitions*. Each partition consists of a module interface file that exports the module partition name. A partition may also have one or more partition implementation files. The module as a whole has one *primary module interface*, which is the public interface of the module. It can export the partition interfaces, if desired.

A module consists of one or more *module units*. A module unit is a translation unit (a source file) that contains a module declaration. There are several types of module units:

- A *module interface unit* is a module unit that exports a module name or module partition name. A module interface unit has `export module` in its module declaration.

- A *module implementation unit* is a module unit that doesn't export a module name or module partition name. As the name implies, it implements a module.

- A *primary module interface unit* is a module interface unit that exports the module name. There must be one and only one primary module interface unit in a module.
- A *module interface unit* exports a module name or module partition name. A module interface unit has `export module` in its module declaration.
- A *module implementation unit* doesn't export a module name or module partition name. As the name implies, it implements a module.
- A *primary module interface unit* exports the module name. There must be one and only one primary module interface unit in a module.
- A *module partition interface unit* exports a module partition name.
- A *module partition implementation unit* has a module partition name in its module declaration, but no `export` keyword.

- A *module partition interface unit* is a module interface unit that exports a module partition name.

- A *module partition implementation unit* is a module implementation unit that has a module partition name in its module declaration, but no `export` keyword.

The **`export`** keyword is used in interface files only. An implementation file can **`import`** another module, but can't **`export`** any names. Implementation files can have any extension.
The **`export`** keyword is only used in interface files. An implementation file can **`import`** another module, but it can't **`export`** any names. Implementation files can have any extension.

## Modules, namespaces, and argument-dependent lookup

The rules for namespaces in modules are the same as in any other code. If a declaration within a namespace is exported, the enclosing namespace (excluding nonexported members) is also implicitly exported. If a namespace is explicitly exported, all declarations within that namespace definition are exported.
The rules for namespaces in modules are the same as any other code. If a declaration within a namespace is exported, the enclosing namespace (excluding members that aren't explicitly exported in that namespace) is also implicitly exported. If a namespace is explicitly exported, all declarations within that namespace definition are exported.

When the compiler does argument-dependent lookup for overload resolutions in the importing translation unit, it considers functions declared in the same translation unit (including module interfaces) as where the type of the function's arguments are defined.

### Module partitions

A module partition is similar to a module, except it shares ownership of all declarations in the entire module. All names exported by partition interface files are imported and re-exported by the primary interface file. A partition's name must begin with the module name followed by a colon. Declarations in any of the partitions are visible within the entire module. No special precautions are needed to avoid one-definition-rule (ODR) errors. You can declare a name (function, class, and so on) in one partition and define it in another. A partition implementation file begins like this:
A module partition is similar to a module, except:
- It shares ownership of all declarations in the entire module.
- All names exported by partition interface files are imported and exported by the primary interface file.
- A partition's name must begin with the module name followed by a colon (`:`).
- Declarations in any of the partitions are visible within the entire module.\
- No special precautions are needed to avoid one-definition-rule (ODR) errors. You can declare a name (function, class, and so on) in one partition and define it in another.

A partition implementation file begins like this, and is an internal partition from a C++ standards perspective:

```cpp
module Example:part1;
```

The partition interface file begins like this:
A partition interface file begins like this:

```cpp
export module Example:part1;
```

To access declarations in another partition, a partition must import it, but it can only use the partition name, not the module name:
To access declarations in another partition, a partition must import it. But it can only use the partition name, not the module name:

```cpp
module Example:part2;
import :part1;
```

The primary interface unit must import and re-export all of the module's interface partition files like this:
The primary interface unit must import and re-export all of the module's interface partition files, like this:

```cpp
export import :part1;
export import :part2;
...
```

The primary interface unit can import partition implementation files, but can't export them. Those files aren't allowed to export any names. This restriction enables a module to keep implementation details internal to the module.

## Modules and header files

You can include header files in a module source file by putting the `#include` directive before the module declaration. These files are considered to be in the *global module fragment*. A module can only see the names in the global module fragment that are in headers it explicitly includes. The global module fragment only contains symbols that are used.
You can include header files in a module source file by putting an `#include` directive before the module declaration. These files are considered to be in the *global module fragment*. A module can only see the names in the global module fragment that are in the headers that it explicitly includes. The global module fragment only contains symbols that are used.

```cpp
// MyModuleA.cpp
Expand Down
12 changes: 6 additions & 6 deletions docs/cpp/tutorial-named-modules-cpp.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,19 +92,19 @@ This line identifies this file as the primary module interface and gives the mod

This name is also where the "named" in "named module" comes from. The files that are part of this module use this name to identify themselves as part of the named module. A named module is the collection of module units with the same module name.

We should talk about the API we'll implement for a moment before going further. It impacts the choices we make next. The API represents different shapes. We're only going to provide a couple shapes in this example: `Point` and `Rectangle`. `Point` is meant to be used as part of more complex shapes, such as `Rectangle`.
We should talk about the API we'll implement for a moment before going further. It impacts the choices we make next. The API represents different shapes. We're only going to provide a couple shapes in this example: `Point` and `Rectangle`. `Point` is meant to be used as part of more complex shapes such as `Rectangle`.

To illustrate some features of modules, we'll factor this API into pieces. One piece will be the `Point` API. The other part will be `Rectangle`. Imagine that this API will grow into something more complex. The division is useful for separating concerns or easing code maintenance.

So far, we've created the primary module interface that will expose this API. Let's now build the `Point` API. We want it to be part of this module. For reasons of logical organization, and potential build efficiency, we want to make this part of the API easily understandable on its own. To do so, we'll create a *module partition* file.
So far, we've created the primary module interface that will expose this API. Let's now build the `Point` API. We want it to be part of this module. For reasons of logical organization, and potential build efficiency, we want to make the code for this part of the API a *module partition* file.

A module partition file is a piece, or component, of a module. What makes it unique is that it can be treated as an individual piece of the module, but only within the module. Module partitions can't be consumed outside of a module. Module partitions are useful for dividing the module implementation into manageable pieces.
Module partitions are useful for dividing the module implementation into manageable pieces. A module partition file is a piece, or component, of a module. What makes it unique is that it can be treated as an individual piece of the module--but only within the module. Module partitions can't be consumed outside of a module.

When you import a partition into the primary module, all its declarations become visible to the primary module regardless of whether they're exported. Partitions can be imported into any partition interface, primary module interface, or module unit that belongs to the named module.

## Create a module partition file

### `Point` module partition
### `Point` module partition example

To create a module partition file, in the **Solution Explorer** right-click **Source Files**, then select **Add** > **Module**. Name the file *`BasicPlane.Figures-Point.ixx`* and choose **Add**.

Expand All @@ -123,11 +123,11 @@ export struct Point

The file starts with `export module`. These keywords are also how the primary module interface begins. What makes this file different is the colon (`:`) following the module name, followed by the partition name. This naming convention identifies the file as a *module partition*. Because it defines the module interface for a partition, it isn't considered the primary module interface.

The name `BasicPlane.Figures:Point` identifies this partition as part of the module `BasicPlane.Figures`. (Remember, the period in the name has no special meaning to the compiler). The colon indicates that this file contains a module partition named `Point` that belongs to the module `BasicPlane.Figures`. We can import this partition into other files that are part of this named module.
The name `BasicPlane.Figures:Point` identifies this partition as part of the module `BasicPlane.Figures` (remember, the period in the name has no special meaning to the compiler). The colon indicates that this file contains a module partition named `Point` that belongs to the module `BasicPlane.Figures`. We can import this partition into other files that are part of this named module.

In this file, the `export` keyword makes `struct Point` visible to consumers.

### `Rectangle` module partition
### `Rectangle` module partition example

The next partition we'll define is `Rectangle`. Create another module file using the same steps as before: In **Solution Explorer**, right-click on **Source Files**, then select **Add** > **Module**. Name the file *`BasicPlane.Figures-Rectangle.ixx`* and select **Add**.

Expand Down