- Table of Contents
- Previous Chapter
- Next Chapter

# Chapter 25: Modules

Since the introduction of header files in the C programming language header files have been the main tool for declaring elements that are not defined but are used in source files. E.g., to use `printf` in `main` the preprocessor directive `#include <stdio.h>` had to be specified.

Header files are still extensively used in C++, but gradually some drawbacks emerged. One minor drawback is that, in C++, header files frequently not merely contain function and variable declarations but often also type definitions (like class interfaces and enum definitions). When designing header files the software engineer therefore commonly distinguishes headers which are merely used inside a local (class) context (like the internal-header approach advocated in the C++ Annotations) and header files which are used externally. Those latter header files need include guards to prevent them from being processed repeatedly by sources (indirectly) including them. Another, important, drawback is that a header file is processed again for every source file including it. Such a task is not a trivial one. E.g., if a header file includes `iostream` and `string` then that forces a compiler like `g++ 14.2.0` to process over 900,000 bytes of code for every source file including that header.

To speed up compilations precompiled headers were introduced. Although the binary format of precompiled headers does indeed allow the compiler to parse the content of header files much faster than their standard text format, they are also very large. A precompiled header merely including `iostream` and `string` exceeds 25 MB: a bit more than its uncompiled text-file equivalent....

Modules were introduced to avoid those complications. Although modules can still include header files, it's a good design principle to avoid including header files when designing modules. In general: once a module has been designed its use doesn't require processing header files anymore, and consequenly programs that merely use modules are compiled much faster than corresponding programs that use header files.

There is another, conceptual, feature of modules. The initial high-level programming languages (like Fortran and Algol) (but also assembly languages) provided functions (a.k.a. subroutines and procedures) to distinguish conceptually different task levels. Functions implement specific tasks. A program reading data, then processing the data, and finally showing the results can easily be designed using functions, and is much easier to understand than replacing the function calls by their actual implementations:

        int main()
        {
            readData();
            processData();
            showResults();
        }

Often such functions use their own support functions, etc, etc, until trivial decomposition levels are reached where simple flow control and expression statements are used.

This decomposition methodology works very good. It still does. But at the global level a problem does exist: there's little integrity protection. Function parameters may help to maintain the program's data integrity, but it's difficult to ensure the integrity of global data.

In this respect classes do a much better job. Their `private` sections offer means for class-designers to guarantee the integrity of the classes' data.

Modules allow us to take the next step up the (separation or integrity) ladder. Conceptually modules offer program sections which are completely separated from the rest of the program. Modules define what the outside world can use and reach, whether they are variables, functions, or types (like classes). Modules resemble factories: visitors can go to showrooms and meeting halls, but the locations where the actual products are being designed and constructed are not open to the public.

In this chapter we cover the syntax, design, and implementation of modules as offered by the C++ programming language. To use modules with the current edition of the Gnu `g++` compiler (version 14.2.0) `--std=c++26` (or more recent) should be specified as well as the module compilation flag `-fmodules-ts`. E.g.,

        g++ -c --std=c++26 -fmodules-ts -Wall modsource.cc

Unfortunately, currently it's not all sunshine and roses. One (current?) consequence of using modules is that the standard that was specified when compiling those modules is also required when compiling sources using those modules. If the specified standards differ (e.g., the modules were compiled with option `--std=c++26`, but for a source file using those modules `--std=c++23` was specified) then the compilation fails with an error like

        error: language dialect differs 'C++26/coroutines', expected 'C++23/coroutines'

A similar error is reported when the modules were compiled with `--std=c++23` and the module using source file is compiled specifying `--std=c++26`. Therefore, once a new standard becomes available, and a module defining source files is recompiled using the new standard then module source files using that module must also be recompiled using that standard.

At https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103524 an overview is published of the (many) currently reported compiler bugs when modules are compiled by Gnu's `g++` compiler. Many of those bugs refer to internal compiler errors, sometimes very basic code that correctly compiles when modules are not used but that won't compile when using modules. Sometimes reported errors are completely incomprehensible. Another complexity is introduced by the fact that, e.g., a class which is defined inside a module is no longer declared in an interface providing header file. Instead, it is defined in a module defining source file. Consequently, those module-interface defining source files must be compiled before the member functions of such a class can be compiled. But it's not the module's interface's object file that's important at that point. When the module-interface defining source file is compiled the compiler defines a ``module-name'.gcm` file in a sub-directory `gcm.cache` (cf. section 25.3). Whenever a source file that uses the module is compiled the compiler must be able to read that `gcm.cache/module-name.gcm` file. As a software engineer you cannot simply compile such module using source files, but you must ensure that the compiler has access to the proper `module-name.gcm` files.

## 25.1: Syntax

Modules introduce new syntax to C++. In this section the new syntax is summarized. Note that each of the following syntax specifications end in semicolons.

Modules may define sub-components (partitions) defining facilities which may be completely inaccessible outside of the modules themselves. Partitions are covered in section 25.6.

- `export module Name;`
  defines a module interface unit. It must be specified on the source file's first line. `Name` is the module's name, its module-compiled interface unit becomes available in `./gcm.cache/Name.gcm`;

- `module Name;`
  source files implementing a module (partition) component must start with the line `module Name;`, where `Name` is the module's name.

- `export import Name;`
  inside module (partition) interface units or module (partition) source files existing modules are made available using `export import Name;` specifications. Using `export` is optional. In module interface units specifying `export` means that the exported module is also available when sources import the module. E.g.,

          // module interface unit:
          export module Group;
          export import <iostream>;
          ...

          // source file:
          import Group;
          int main()
          {           // cout available via Group
              std::cout << "hello world\n";
          }

- `export module Name:Partition;`
  defines a module partition interface unit. It must be specified on the source file's first line. `Name` is the module's name, `Partition` is a partition of module `Name`. Its compiled interface unit becomes available in `./gcm.cache/Name-Partition.gcm`;

- `export import :Partition;`
  inside module (partition) interface units or module (partition) source files existing module partitions are made available using `export import :Partition;`. In module interface units using `export` is required, otherwise using `export` is optional.

## 25.2: Modules

Modules (and partitions, cf. section 25.6) are designed using source files instead of header files. A module always defines a module interface unit. The module's interface unit is the module's equivalent of a header file. Consider (as used in the C++ Annotations) defining the module's interface in a file named ``modname.cc`' (where `name` is the (possibly lowercase) module's name), located in a sub-directory having the (possibly lowercase) module's name. Using plain (internal) header files should be avoided when defining and/or using modules.

Here's an example of a module's interface. The module's name is `Square` and it declares a function, a class, and a variable:

        export module Square;                           // source: modsquare.cc

        export
        {
            double square(double value);

            class Square
            {
                double d_amount;

                public:
                    Square(double amount = 0);          // initialize
                    void amount(double value);          // change d_amount
                    double amount() const;              // return d_amount

                    double lastSquared() const;         // returns g_squared
                    double square() const;              // returns sqr(d_amount)
            };
        }

        extern double g_squared;

This module interface merely serves as an illustration. In practice module interfaces don't contain many different items, but usually just a single class or, alternatively, a series of utility functions. For now, however, the slightly overpopulated module `Square` is used as an initial illustration.

The interface's top-line exports and defines the module name. This must be the first line of the module's interface unit. Next, the function `square` and `class Square` are declared inside an `export` compound. It is possible to export componentsindividually, but using an `export compound' is convenient. Exported components can be used outside of the module. Non-exported components (like `g_squared`) are only available to the module's components, and are therefore like global components, albeit with a restricted (module) scope.

Also note that the variable `g_squared` is listed in the interface as `extern double g_squared`: it is therefore a declaration, not a definition. To define variables in a module omit `extern` (as in `double g_squared`), but to avoid overpopulating modules it's advised to merely put declarations in module interface units.

The `modsquare.cc` file can now be compiled, requiring the `-fmodules-ts` compiler option:

       g++ -c --std=c++26 -fmodules-ts -Wall modsquare.cc

Compiling `modsquare.cc` not only produces the file `modsquare.o`, but also a sub-directory `gcm.cache`, containing the `module compiled interface file' `Square.gcm`, which is somewhat comparable to a traditional pre-compiled header file. This `.gcm` file must be available when compiling source files implementing components of module `Square`, and it must also be available to other source files that import (i.e., use) module `Square`. Consequently, the directories containing such files must therefore also have `gcm.cache` sub-directories containing the `Square.gcm` file. This requirement is complex, and in practice a so-called modmapper (cf. section 25.7) is used to handle the complexity. A simple way to make module compiled interface files available to all sections of a project is by defining a top-level directory `gcm.cache` and using soft-links (like `square/gcm.cache`) to the top-level's `gcm.cache` directory. The top-level `gcm.cache` directory and the soft-links in the project's sub-directories can be prepared before compiling `square/modsquare.cc` resulting in the following directory structure:

        .
        +-- gcm.cache
        |   +-- Square.gcm
        |
        +-- square
            +-- gcm.cache -> ../gcm.cache

All components of the module `Square` must specify that they're part of that module. Traditionally this is realized by using (internal) header files. But projects using modules should no longer need header files. Instead of the (traditionally used) `square.h` and `square.ih` files a module frame file, tailored to the modules' requirements can be used when defining source files belonging to modules. In this example the requirement for the remaining source files of the `Square` module is simple: just specify that the source file belongs to the `Square` module. Here's a basic `frame` file, tailored to the members of the `class Square`:

        module Square;

        Square::()
        {
        }

The function square isn't part of the `class Square`, so when it's defined the `Square::` scope is omitted:

        module Square;

        double square(double value)
        {
            return g_squared = value * value;
        }

But the members of the `class Square` can be defined as usual after copying the `frame` file to the source filew defining those members. Here is `Square's` constructor:

        module Square;

        Square::Square(double amount)
        :
            d_amount(amount)
        {}

and the other members are defined analogously:

        module Square;

        void Square::amount(double value)
        {
            d_amount = value;
        }

        module Square;

        double Square::amount() const
        {
            return d_amount;
        }

        module Square;

        double Square::lastSquared() const
        {
            return g_squared;
        }

        module Square;

        double square(double value)
        {
            return g_squared = value * value;
        }

As an aside: the members of this class `Square` are all very simple, and instead of defining them in separate source files they could also be defined `inline` in the `module.cc` file itself. Since the class `Square's` interface is exported its members are too, and inline implementations of its members don't have to be provided in the export compound.

The module can now be used by, e.g., the program's `main` function. Source files importing a module must import that module, and if multiple source files are defined in the top-level directory (like `main.cc, usage.cc,` etc.), that directory can define its own `frame` file. In this initial example there's only a single `main.cc` source file, which merely has to import module `Square`. But since it also uses `std::cout` it must import the module compiled system header `iostream` (cf. section 25.3.1):

        import Square;
        import <iostream>;

        int main(int argc, char **argv)
        {
            std::cout << "the square of " << argc << " is " << square(argc) << '\n';
            Square obj{12};
            std::cout << "the square of 12 is " << obj.square() << "\n"
                        "the last computed square is " << obj.lastSquared() << '\n';

        }

The `gcm.cache` directories are only required during compilation time. The linker doesn't use them and once the source files have been compiled a program can be constructed as before, by linking the object files, resulting in a binary program.

This example illustrates several characteristics of modules:

- module interfaces start with `export module` followed by the module's name. Module names are identifiers, possibly followed by ``. identifier`' sequences (like `My.Module`).

- module names containing a colon (like `:name` or `name1:name2`) are also encountered. Such names refer to module partitions, covered in section 25.6.

- module interface units must begin with an `export module 'module-name'` line. Therefore module interface files cannot define multiple modules;

- components which are accessible to sources outside of the module itself must be specified in an `export` compound or must be specified using their own initial `export` keyword. If no `export` is used the component is only accessible to the components of the module;

- When using modules project header files are not used anymore. Module compiled system headers (like in `import <iostream>;`) are used, but preprocessor directives like `#include <iostream>` aren't.

- Since module interface units are source files include guards aren't required anymore.

- Since header files are not used anymore the compiler doesn't have to read thousands of lines of header files anymore, significantly reducing compilation times.

## 25.3: The gcm.cache directory

When using modules the module interface units must be compiled before other sources using the modules or implementing their components can be compiled. This also holds true for partition interface units (cf. section 25.6). When a module interface unit is compiled the compiler stores the module's `.gcm` file (the equivalent of a compiled header file) in the `gcm.cache` sub-directory of the module interface unit. If the module's name is `Square`, defined in the `modsquare.cc` source file then the compiler produces `gcm.cache/Sqaure.gcm` as well as the `modsquare.o` object file. The `.gcm` file must be available to any source file importing the module or implementing one of the module's components.

Usually projects define several sub-directories, and files in those sub-directories (as well as files in the top-level directory) may import modules defined in other sub-directories. To ensure that module-compiled interface units are available to all of the program's source files the following setup can be adopted:

- The top-level directory defines a `gcm.cache` sub-directory
- Each of the project's sub-directories defines a soft-link `gcm.cache -> ../gcm.cache`

This setup works fine as long as all the project's modules have different names, but that by itself is a good design principle.

### 25.3.1: Module-compiled system header files

Traditionally system header files were included to declare classes like `std::string` and `std:ostream`. But when using modules including headers is deprecated and instead their module-compiled equivalents should be imported using `import` statements.

To avoid recompiling system header files for different projects consider storing module-compiled headers in `/usr/include/c++/14` (here, '14' is `g++'s` main version number: update it to your actually installed version). Using the procedure described in this section project source files can import module-compiled system headers (assuming that projects have defined `./gcm.cache` directories as described in the previous section).

- In the project's `gcm.cache` directory define the soft-link `usr -> /usr`;
- To construct the module-compiled version of a system header file (e.g., `iostream -> iostream.gcm`) then as execute root in `/usr/include/c++/14` execute the command

          g++ --std=c++26 -fmodules-ts -x c++-system-header iostream

  (if the C++ standard isn't `c++26` then adapt it to the C++ standard that should be used)
- Then move the file `iostream.gcm` to the current directory:

          mv gcm.cache/usr/include/c++/14/iostream.gcm .

The same procedure can also be used to module-comile header files of installed libraries. E.g., the bobcat(7) library stores its headers in `/usr/include/bobcat`. To module-compile its `arg` header file:

- `cd /usr/include`
- `g++ --std=c++26 -fmodules-ts -x c++-system-header bobcat/arg`
- `mv gcm.cache/usr/include/bobcat/arg.gcm bobcat/`

Note: currently (using `g++` version 14.2.0) compilation sequence issues may be encountered when module-compiling system headers. For some system headers module-compilation fails if some other module-compiled system headers are already available. Those issues can usually be `solved' by first moving all existing .gcm files to, e.g., a `./tmp` sub-directory, followed by the module-compilation of the intended system header file, and then moving the `tmp/*.gcm` files back to the current directory.

### 25.3.2: Module-compiled headers of locally developed libraries

In addition to header files used for system libraries locally developed libaries exist. Such libraries may very well have traditionally been developed, using standard header files. But once project start using modules it might be attractive to convert the traditional header files to module-compiled header files.

To module-compile a standard header file (e.g., an existing `support.h` header file in a `support` sub-directory) to a module-compiled header file issue the command

        g++ --std=c++26 -Wall -fmodules-ts -x c++-header support.h

The compiler then writes the module-compiled header file `support.h.gcm` in the `./gcm.cache/,/` sub-directory (note: in `gcm.cache's` `comma' sub-directory).

When a library is constructed there are usually multiple header files, between which some hierarchy may exist. Consider a library consisting of three classes: `Top`, depending on `Middle`, which in turn depends on `Base` Each class is defined in its own sub-directory. E.g., `base/base.h`:

        #ifndef INCLUDED_BASE_
        #define INCLUDED_BASE_

        #include <fstream>

        class Base
        {
            std::ifstream d_in;
            public:
                Base();
        };

        inline Base::Base()
        :
            d_in("demo.in")
        {}

        #endif

`middle/middle.h`:

        #ifndef INCLUDED_MIDDLE_
        #define INCLUDED_MIDDLE_

        #include <string>

        #include "../base/base.h"

        class Middle
        {
            std::string d_text;
            Base d_base;
        };

        #endif

and `top/top.h`:

        #ifndef INCLUDED_TOP_
        #define INCLUDED_TOP_

        #include <vector>
        #include "../middle/middle.h"

        class Top
        {
            std::vector<std::string> d_vect;
            Middle d_middle;
        };

        #endif

To module-compile the library's headers the `gcm.cache` organization as described in section 25.2 is used (a `gcm.cache` directory is defined at the project's top-level directory, while sub-directories define `gcm.cache` soft-links to the top-level `gcm.cache` directory). Next each header file is module-compiled whereafter the `gcm.cache` subdirectory contains:

        ,/base.h.gcm
        ,/middle.h.gcm
        ,/top.h.gcm
        usr -> /usr

This, however, is not the organization which is expected by programs that need to use the module-compiled headers. To compare: the module-compiled system header files are, together with the system header files themselves, located in `/usr/include/c++/14` (like `iostream` and `iostream.gcm`). When module-compiled headers should be used by programs a similar organization is expected. But that's easily realized by defining a sub-directory (e.g., `hdrs`) containing soft-links to each of the library's header files and to each of the library's module-compiled header files. If `hdrs` is a sub-directory of the libraary's top-level directory then it contains

        base.h       -> ../base/base.h
        base.h.gcm   -> ../gcm.cache/,/base.h.gcm
        middle.h     -> ../middle/middle.h
        middle.h.gcm -> ../gcm.cache/,/middle.h.gcm
        top.h        -> ../top/top.h
        top.h.gcm    -> ../gcm.cache/,/top.h.gcm

As elaborated in the following two sub-sections there are two ways programs using the local library can import the library's module-compiled headers: by using a relative path to the `hdrs` sub-directory or by using an absolute path to the `hdrs` subdirectory.

#### 25.3.2.1: Using a relative location

Once the local library's headers and module-compiled headers are available via the local library's `hdr` sub-directory they can be imported by source files which do not belong to the library.

Suppose the library's header files are imported by `main.cc`, defined in the directory `~/project`:

        import "base.h";
        import "middle.h";
        import "top.h";

        int main()
        {
            Base base;
            Middle middle;
            Top top;
        }

Furthermore, assume the local library's top-level directory is `~/support/locallib` (and so `~/support/locallib/hdrs` contains the soft-links to its header files and module-compiled header files).

To make the library's headers available to `main.cc` two soft-links to relative destinations can be defined:

- in `~/project` define a soft-link to the library's `hdrs` directory:

          ln -s ../support/locallib/hdrs .

- in the `~/project/gcm.cache/,/` (note: comma!) sub-directory define a soft-link to the just defined `hdrs` soft-link:

          ln -s ../../hdrs .

Once these links are available `main.cc` can be compiled using

        g++ -c --std=c++26 -fmodules-ts -isystem hdrs main.cc

- In practice the program using the library's headers also needs linker options: these are used as always, and need no further modifications.
- The soft-links must be relative links: if the local library's `hdr` is located in a completely different location then the soft-link `~/project/hdrs` must point to that directory using a relative path specification.
- The names of the two soft-links must be identical, but the name of the project's soft-link to the library's `hdrs` directory does not have to be `hdrs`.

#### 25.3.2.2: Using an absolute location

When importing a local library's header using two soft-links to relative destinations it's also possible to define a single soft-link to the absolute location of the directory containing the library's headers. There's no compelling reason for using relative or absolute destinations. Maybe if the relative path specification becomes complex using the absolute destination is slightly more attractive.

Using the `~/project/main.cc` from the previous section define a soft-link to the absolute location of the library's `hdrs` sub-directory in the project's `gcm.cache` sub-directory (note: here no comma is used):

        ln -s ~/support/locallib/hdrs gcm.cache

Next compile `main.cc` using

    g++ -c -fmodules-ts -isystem ~/support/locallib/hdrs main.cc

- In `gcm.cache` the full path to `hdrs` is not required, but at least first sub-directory name must be be specified (since `~/...` refers to the user's home directory, which commonly begins at `/home/...` the link could be defined as `ln -s /home gcm.cache/`).
- The soft-link name itself can freely be chosen and doesn't have to be equal to the final destination. E.g., after defining the links

          ln -s ~/support/locallib/hdrs /tmp/locallib
          ln -s /tmp gcm.cache

  the compilation command is:

          g++ -c -fmodules-ts -isystem /tmp/locallib main.cc

### 25.3.3: Local header files

Although local header files can also be module-compiled doing so is deprecated as using (local) headers is probably a left-over from the traditional program development era.

But, for the sake of completeness, local header files can be module-compiled. But note that once a header file is compiled `using namespace` declarations specified in header files are lost when the header file is either included or imported. Compiled local header files are stored in the `gcm.cache/,/` (note: a comma) sub-directory. They're automatically used when either their header files are included (e.g., `#include "header.h"`) or imported (using `import "header.h";`).

## 25.4: Namespaces

Modules and namespaces are mutually independent. Modules (and/or partitions, cf. section 25.6) can define (contain) namespaces and/or they can define components in namespaces. Source files importing such modules must either explicitly specify the namespace of such components or they can specify a `using namespace` declarations avoiding the explicit namespace specification when referring to components living in those namespaces.

Here is a simple example of a module exporting a variable which is defined in a namespace:

        export module NS;

        export import <cstddef>;

        export namespace FBB
        {
            extern size_t g_count;
        }

It's a very basic example, illustrating the essence of defining a namespace completely covering the module's export compound. Variations are possible: a namespace could completely surround the export compund, a namespace could be defined inside the export compound, only some of the module's components could belong to a namespace, non-exported components could belong to a namespace, multiple namespaces could be used, etc., etc..

To use the variable `g_count`, its module is imported and its namespace is specified as usual. E.g.,

        import NS;

        import <iostream>;

        int main()
        {
            ++FBB::g_count;

            std::cout << FBB::g_count << '\n';
        }

Alternatively the source file could specify some `using namespace` declarations so the repeated namespace specifications can be avoided:

        import NS;
        import <iostream>;

        using namespace std;
        using namespace FBB;

        int main()
        {
            ++g_count;
            cout << g_count << '\n';
        }

Some notes:

- Since module interfaces must start with `export module` modules cannot be defined inside namespaces. Constructions like

          namespace Area
          {
              export module Nested;
              ... declarations of components of Nested
          }

  won't compile. But as shown, defining a namespace section inside a module is fine.
- Modules cannot be imported inside a namespace area as `import` declarations cannot be nested (i.e., they must be at global scope) So constructions like the following also won't compile:

          namespace FBB
          {
              import NS;
          }

## 25.5: Templates

Templates are recipes used by the compiler to construct code tailored to specific types. Since they're recipes they cannot be compiled to running code. Traditionally templates are implemented in header files, and when used the compiler instantiates templates with the correct types using the templates' recipes.

Since modules are defined in source files there are no header files anymore when using modules. Modules specify their components in source files, replacing the traditional header files: by defining templates in a module interface unit the template's recipe character is kept, and they are instantiated when needed.

Here's an initial example. A `module Adder` exports a function template `add` adding two values and returning their sum:

        export module Adder;

        export
        {
            template <typename Type>
            Type add(Type const &t1, Type const &t2)
            {
                return t1 + t2;
            }
        }

Source files importing `Adder` can now add values of types supporting the `+` operator:

        import Adder;

        import <iostream>;
        import <string>;

        using namespace std;

        int main()
        {
            cout << add(1, 2) << '\n' <<
                    add(1.1, 2.2) << '\n' <<
                    add("hello "s, "world"s) << '\n';
        }

producing the following output:

        3
        3.3
        hello world

### 25.5.1: Class templates

In the previous section a function template was defined in a module interface unit. This section covers the definition of a class template. The class template `SortMap` offers the facilities of an `unordered_map`, but also has two `sort` members. Both return a vector with pointers to the elements of the unordered map. One member returns pointers to the elements sorted by their key values, the other member receives a functor, returning a vector of pointers to the elements which are sorted according to the functor's decisions.

The module interface unit defines the `SortMap` module. It declares the class template `SortMap`. The module, like any module, can be imported in other source files, like a source file `main.cc`. The `main` function inserts its arguments into `SortMap` and then shows the inserted values: first ordered by the map's keys, then ordered by the map's values:

        import SortMap;

        import <iostream>;
        import <string>;

        using namespace std;

        int main(int argc, char **argv)
        {
            SortMap<string, size_t> sortMap;

            for (; argc--; )                                    // fill sortMap
                sortMap.emplace(argv[argc], argc);

            for (auto const *ptr: sortMap.sort())               // sort by key
                cout << ptr->first << ' ' << ptr->second << "; ";
            cout.put('\n');

            for (auto const *ptr: sortMap.sort(                 // sort by value
                                        [&](auto const &lhs, auto const &rhs)
                                        {
                                            return lhs->second < rhs->second;
                                        }
                                    )
            )
                cout << ptr->first << ' ' << ptr->second << "; ";
            cout.put('\n');
        }

When calling `a.out one two three four five six` it outputs

        a.out 0; five 5; four 4; one 1; six 6; three 3; two 2
        a.out 0; one 1; two 2; three 3; four 4; five 5; six 6

All members of class templates are templates, and as with header files containing class templates there's only one source file defining the module interface unit: it contains the class template's interface and also the implementations of its members. There is, however, an escape route: it's covered in section 25.6. But in this section the standard way to implement class templates is covered.

When using a single file there's maybe one drawback: the module interface unit, as it must contain the full implementation of the class template, may quickly grow to a very large file, which is hard to maintain. To simplify maintenance it is advised to adopt here the one function, one file design principle also: the module interface unit itself exports the class interface, and then uses an `#include` preprocessor directive to add the class members' implementations:

        export module SortMap;

        export import <unordered_map>;
        export import <vector>;
        import <algorithm>;

        export
        {
            template <typename Key, typename Value>
            class SortMap: public std::unordered_map<Key, Value>
            {
                using UMap = std::unordered_map<Key, Value>;
                using ValueType = typename UMap::value_type;
                using Vect = std::vector<ValueType const *>;

                private:
                    Vect d_sortVect;

                public:
                    Vect const &sort();             // sort the keys        // 1.f

                    template <typename Functor>     // use a functor        // 2.f
                    Vect const &sort(Functor const &functor);
            };
        }

        #include "sortmap.f"

The design of the `class SortMap` itself is standard. At the top of the module interface unit the `SortMap` module name is defined followed by importing some module compiled system header files. Since `algorithm` is only used internally by the member functions it's not exported. But imported components must be specified at the top of module source files, and so `algorithm` cannot be imported by, e.g., `sortmap.f`.

The file `sortmap.f` itself merely includes the files implementing the two `sort` members, keeping the module interface unit as clean as possible. Here is `sortmap.f`:

        #include "sort1.f"
        #include "sort2.f"

Each of its included files contain the definition of one member function. A comment in the class's interface indicates which function is defined in which file. Here's the first `sort` member (`sort1.f`):

        template <typename Key, typename Value>
        SortMap<Key, Value>::Vect const &SortMap<Key, Value>::sort()
        {
            d_sortVect.clear();

            for (auto const &el: *this)
                d_sortVect.push_back(&el);

            std::sort(d_sortVect.begin(), d_sortVect.end(),
                [&](auto const *lhs, auto const *rhs)
                {
                    return lhs->first < rhs->first;
                }
            );

            return d_sortVect;
        }

And here's the second `sort` member, accepting a functor (`sort2.f`)

        template <typename Key, typename Value>
        template <typename Functor>
        SortMap<Key, Value>::Vect const &SortMap<Key, Value>::sort(
                                                Functor const &functor)
        {
            d_sortVect.clear();

            for (auto const &el: *this)
                d_sortVect.push_back(&el);

            std::sort(d_sortVect.begin(), d_sortVect.end(), functor);

            return d_sortVect;
        }

## 25.6: Partitions

In the introduction section of this chapter it was stated that modules offer new, conceptual features: modules offer program sections which are completely separated from the rest of the program, but modules themselves can define subsections (called partitions) which can define components (classes, types, variables, etc.) which are only accessible to the module and its partitions.

Within the restriction that partitions can be defined so that they're only accessible to their module and their sibling-partitions the access rights of classes defined in partitions are identical to those of classes in general: public members are accessible to their users, protected members are available to classes derived from those classes, while private members cannot be accessed from outside of those classes.

Figure 36: Partitions of the `Math' module

Figure 36 illustrates a simple module (`Math`) having two partitions. It shows the relationships between the module and its partitions in the same way as commonly used for classes: the most basic (least dependent) partition is on top, the partition depending on the topmost partition is in the middle, and the module itself, depending on both partitions, is at the bottom. The `Math` module defines a class `Math`, having a member returning the sum of two `size_t` values and a member `count` returning the number of performed additions. It's a very basic design merely illustrating the way partitions are designed.

The object of `class Add` performs an addition, and the object of `class Utility` keeps track of the number of additions that were performed. Both `Add` and `Utility` are defined as classes in their own partitions: `Math:Utility` and `Math:Add`.

Note that partitions themselves are not classes. When defining a partition interface unit only a single colon is used instead of two, as used then defining cass member functions (so `Math:Utility` and not `Mat::Utility`).

The `Math` interface unit exports `class Math`, allowing code which does not belong to the module `Math` itself to define `Math` objects after importing the `Math` module:

        import Math;
        void fun()
        {
            Math math;
            ...
        }

Since the `class Math` has data members `Utility d_util` and `Add d_add` these classes must be known inside the `Math` module interface unit (`modmath.cc`), but also by software defining objects of `class Math` (comparable to the requirement to, e.g., include `<string>` when a class defines a `std::string` data member). Therefore the `Math` module interface unit specifies `export import` for the `Utility` and `Add` partitions. As we'll shortly see these `export` specifications do not imply that software merely using the facilities of the `Math` module can also define, e.g., `Math:Utility` objects: the partitions can still remain `private' to the `Math` module. Here is the `Math` module interface unit, defined in `math/modmath.cc`:

        export module Math;

        export import :Utility;
        export import :Add;

        export
        {
            class Math
            {
                Utility d_util;
                Add d_add;

                public:
                    Math();
                    size_t count() const;
                    size_t add(size_t lhs, size_t rhs);
            };
        }

The design of the module `Math` defining partitions introduces a completely new level of separation: the components of partitions are like nested classes but don't result in `class overpopulation': partitions are not defined inside modules but are completely separately defined from their modules, while making their facilities only available to their modules and sibling partitions. And although probably not illustrating good design: by defining `export` compounds in partition interface units the elements in those compounds become directly available to using software essentially turning the partition into a module.

### 25.6.1: The Math:Utility partition

The `Math:Utility` partition is the most basic of the two `Math` partitions. It does not depend on features of either the `Math` module or the `Math:Add` partition. Since it does use the `size_t` type, it specifies `export import <cstddef>`. Here, because of its `export` specification, the definitions in `cstddef` are also available when `Utility` is imported, and since the `Math` module itself exports `:Utility` also to software importing `Math`.

As `Utility` is a `Math` partition its partition interface unit starts by specifing this:

        export module Math:Utility;

The colon indicates that this is not a plain module but a partition (note that the first line must start by specifying `export`). It contains only non-exported components, but as it's a partition of a module, all the partition's components are fully available to its module and its sibling partitions. Its `class Utility` has two simple members, both very simple, never changing one-liners. Because of that they're implemented in-line. Here's the `Utility` partition interface unit:

        export module Math:Utility;

        export import <cstddef>;

        class Utility
        {
            size_t d_count;

            public:
                Utility();

                void inc();
                size_t count() const;
        };

        inline void Utility::inc()
        {
            ++d_count;
        }

        inline size_t Utility::count() const
        {
            return d_count;
        }

Defining members inline is not required, but is an option. For example, its constructor could very well also have been defined inline, but (for illustration purposes) is defined in a separate source file. As `Utility's` constructor is a partition source file it starts by specifying its module (`Math`), followed by importing the partition component (`:Utility`) which is defined in this source file:

        module Math;
        import :Utility;

        Utility::Utility()
        :
            d_count(0)
        {}

### 25.6.2: The Math:Add partition

Different from the `Math:Utility` partition the `Math:Add` partition does depend on another partition: it depends on `Math:Utility`. Like `Utility's modutility.cc` it starts its `modadd.cc` file by exporting its partition name. But then it imports `:Utility`, since that partition is used by `Math:Add`, making available all components of that partition.

Since `:Utility` already imports `<sstddef> :Add` can also use `size_t`. For `:Add` the `:Utility` partition wouldn't have to specify `export` in front of `import <stddef>` since all components of imported partitions are available to both the module and its partitions. But by using `export import <cstddef>` users of the `Math` module automatically receive `<cstddef>'s` definitions (among which `size_t`). Here's the `Math::Add` partition interface unit (again: notice that the interface doesn't contain an export compound):

        export module Math:Add;

        import :Utility;

        class Add
        {
            Utility &d_utility;

            public:
                Add(Utility &utility);
                size_t sum(size_t lhs, size_t rhs);
        };

For this partition no members were defined inline (although that would also have been possible). Instead all members were defined in separate source files. Here is `class Add's` constructor:

        module Math;
        import :Add;

        // export import :Utility;  OK, but superfluous

        Add::Add(Utility &utility)
        :
            d_utility(utility)
        {}

and its `sum` member:

        module Math;
        import :Add;

        size_t Add::sum(size_t lhs, size_t rhs)
        {
            d_utility.inc();
            return lhs + rhs;
        }

### 25.6.3: The Math module's members

Now that the interfaces of the `Math` module and its partitions have been defined (cf. figure 36) the `Math` module's members can be defined. The constructor of `class Add` in the `Math:Add` partition needs a reference to a `Utility` object which it receives from `Math` constructor:

        #include "math.i"
        //import Math;

        Math::Math()
        :
            d_add(d_util)
        {}

Since `class Utility's count` member is public, it can be called by the `Math::count` member:

        import Math;

        size_t Math::count() const
        {
            return d_util.count();
        }

and finally, `Math's add` member calls `Add's sum` member, defined in the `Math:Add` partition to obtain the sum of two positive integral values:

        import Math;

        size_t Math::add(size_t lhs, size_t rhs)
        {
            return d_add.sum(lhs, rhs);
        }

### 25.6.4: Using the Math module

Now that the `Math` module has been developed it can be used by a program. The exported facilities offered by a module are available after importing the module. Note that although a module may `export import` its partitions only partition components defined in their `export` compound are available to source files not belonging to the module itself. As `Math:Utility` exports `<cstddef>` source files importing `Math` automatically also can use `cstddef's` features.

Here's a `main` function importing `Math` and using its facilities to add two positive integral numbers. Header files are not used anymore, and the implementation of the `main` function is equal to the implementation when using header files. However, compared to the latter implementation the compilation of a program using modules requires significantly less time, and the design of modules using partitions may offer better isolation of components that are mere building blocks of the those modules.

Here is the implementation of the `main` function using the `Math` module:

        import Math;
        import <iostream>;

        using namespace std;

        int main()
        {
            Math math;

            cout << "Initial number of additions: " << math.count() << "\n"
                    "Enter two pos. values to add: ";

            size_t lhs;
            size_t rhs;
            cin >> lhs >> rhs;
            cout << "their sum is " << math.add(lhs, rhs) << "\n"
                    "total number of performed additions: " << math.count() << '\n';
        }

### 25.6.5: Partitioned class templates

In section 25.5.1 the a class template `SortMap` was defined in a module interface unit. Like class templates in header files class templates in a module interface files may grow large because the file not only contains the class template's interface but also the implementations of its members. Consequently a full recompilation is required when only a single member function is modified. Recompilations cannot completely be avoided, but by using module partitions complete recompilation can often be avoided.

Some maintenance complications, however, remain: once a class template's member is modified the modification is not visible in members that use that member. But this dependency issue always plays a role when using templates: once a template has been modified all code using the template needs to be recompiled.

In the current section class templates are implemented using module partitions, each containing a member of the class template. The previously developed `SortMap` module consists of three components: the class interface and two `sort` members functions. Now when using partitions each component will be defined in its own partition, and the module itself contains `export import` statements for each partition which must be accessible by code using the module. Consequently the `modsortmap.cc` module interface unit is remarkably simple:

        export module SortMap;

        export import :Interface;
        export import :Sort1;
        export import :Sort2;

Note that even the class interface is defined in a partition: it cannot be defined in the module interface unit itself, since partitions can depend on other partitions, but not on the module itself as the partitions must (as they are imported by the module) be available before the module itself can be compiled. Partitions, however, can depend on other partitions, so a partition implementing a `sort` function can import a partition providing the class's interface.

As the `:Interface` partition merely specifies what's offered by the `class SortMap` it doesn't depend on the other partitions. So it merely declares but does not contain the implementations of the `sort` members, and thus it does not itself have to import the `alorithm` module-compiled header:

        export module SortMap:Interface;

        export import <unordered_map>;
        export import <vector>;

        export
        {
            template <typename Key, typename Value>
            class SortMap: public std::unordered_map<Key, Value>
            {
                using UMap = std::unordered_map<Key, Value>;
                using ValueType = typename UMap::value_type;
                using Vect = std::vector<ValueType const *>;

                private:
                    Vect d_sortVect;

                public:
                    Vect const &sort();             // sort the keys        // 1.f

                    template <typename Functor>     // use a functor        // 2.f
                    Vect const &sort(Functor const &functor);
            };
        }

On the other hand, the implementations of the two `sort` members do depend on the interface, since they implement their declarations. They also depend on the facilities provided by the `algorithm` module-compiled header. Both are therefore imported. Here's the implementation of the first `sort` member in the `:Sort1` partition:

        export module SortMap:Sort1;

        import :Interface;
        import <algorithm>;

        export
        {
            template <typename Key, typename Value>
            SortMap<Key, Value>::Vect const &SortMap<Key, Value>::sort()
            {
                d_sortVect.clear();

                for (auto const &el: *this)
                    d_sortVect.push_back(&el);

                std::sort(d_sortVect.begin(), d_sortVect.end(),
                    [&](auto const *lhs, auto const *rhs)
                    {
                        return lhs->first < rhs->first;
                    }
                );

                return d_sortVect;
            }
        }

The second `sort` member is implemented analogously:

        export module SortMap:Sort2;

        import :Interface;
        import <algorithm>;

        export
        {
            template <typename Key, typename Value>
            template <typename Functor>
            SortMap<Key, Value>::Vect const &SortMap<Key, Value>::sort(
                                                    Functor const &functor)
            {
                d_sortVect.clear();

                for (auto const &el: *this)
                    d_sortVect.push_back(&el);

                std::sort(d_sortVect.begin(), d_sortVect.end(), functor);

                return d_sortVect;
            }
        }

The `main` function can remain as provided in section 25.5.1. When constructing the program the partition dependencies must be taken into account:

- first the `:Interface` partition is compiled;
- then, in any order, the `:Sort1` and `:Sort2` partitions are compiled;
- finaly `main.cc` is compiled and the compiled object files are linked resulting in the final program.

## 25.7: Module mapping

Modules cannot mutually import each other. Consequently there's always a linear, non-circular module hierarchy, which should be acknowledged when compiling files defining and using modules. In this section the requirements for projects using modules are covered, as well as a procedure that can be adopted when constructing such projects.

With modules traditional headers (`.h` files) should be avoided. System header files (cf. section 25.3.1) still exist, but for those `import` statements should be used or made available. For locally developed libraries module-compiled header files can also be used (cf. section 25.3.2).

It can be difficult to determine which module sections can immediately be compiled, and which ones depend on already compiled sections. Moreover, source files belonging to modules but not defining their interface units may import modules which aren't yet available when compiling the module's interface unit. For example, module `Basic's` interface unit is independent of other modules:

        export module Basic;

        export
        {
            class Basic
            {
                public:
                    void hello() const;
             };
        }

But a module `Second` imports `Basic` and therefore the compilation of its module interface file depends on the availability of `gcm.cache/Basic.gcm`:

        export module Second;

        export import Basic;
        export import <iosfwd>;

        export
        {
            class Second
            {
                public:
                    static std::string hello();
            };
        }

Consequently `basic/modbasic.cc` must be compiled before compiling `second/modsecond.cc`. However, module `Second` may export a class `Second`, and an object of `class Second` could be defined by a member of the class `Basic`, exported by the `Basic` module:

        module Basic;

        import Second;
        import <iostream>;
        import <string>;

        using namespace std;

        void Basic::hello() const
        {
            cout << Second::hello() << '\n';
        }

In such situations the module interface units must first, and in the right order, be compiled. Then, once they are available the remaining source files of the modules can be compiled.

This two-step process (first compile the module interface units in the right order and then compile the remaining source files) quickly becomes a challenge, which is commonly handled by using a module mapper. Module mappers inspect the modules of a project, building their dependency tree, and maybe compiling the module interface units in the right order. The module mapper icmodmap(1), a utility program of the icmake(1) project, is such a module mapper.

By default (but configurable via options) icmodmap(1) expect projects using modules to be organized as follows:

- The project's top-level directory contains a file `CLASSES`, where each line (ignoring empty lines and C++ comment) specifies the name of a sub-directory implementing one of the project's components. Partitions can be defined in their own sub-directories or in sub-directories of the module to which they belong. Sub-directories do not have to define modules, but all of the project's source files may import modules;
- The top-level directory itself may also define a module;
- If the project defines a program, the project's top-level directory contains source files (like `main.cc` defining the `main` function);
- To simplify locating source files defining module or partition interface units it is advises to start their names with `mod`, followed by the (optionally lower-case) name of the module or partition they define. Following this convention a module `Support` is defined in the file `modsupport.cc`;
- It's considered good practice to export only a single class from a module or parition unit, but (like traditional header files) this is not a formal requirement.

Icmodmap(1) inspects each of the source files in the project's top-level directory and in each sub-directory specified in the `CLASSES` file. If a source file's first line starts with `export module` it's a module or partition interface unit. If so, its module or partition name is stored in a data-base. Since module and partition interface units may themselves import modules and/or partitions the current interface depends on those imported components. Those imported components are declared in its data-base registering that the current interface unit depends on those imported components.

Likewise, if another source file imports modules or implements a component of a module or partition then those modules (and/or paritions) are also declared in its data-base.

Once all source files were inspected icmodmap(1) determines the module dependencies: its data-base must indicate that each imported module or partition also has a module/partition interface unit, and that there are no circular dependencies among the module/partition interface units. If these requirement are satified then icmodmap by default calls the compiler to compile the interface units in their proper order. By default the object files are stored in the standard icmake(1) fashion: each compiled interface unit is stored in the project's `tmp/o` sub-directory and their names begin with a number which is equal to the line number in the `CLASSES` file specifying the inspected sub-directory (like `1modfirst.o, 2modsecond.o,`) using prefix 0 for module(s) defined in the project's top-level directory.

When the inspection and compilation successfully completes then the interface units' object files are stoed in `tmp/o`, and the project's top-level directory contains a sub-directory `gcm.cache` containing the `.gcm` files of all modules and partitions. In addition each inspected sub-directory has received a soft-link `gcm.cache` to its parent's `gcm.cache` sub-directory, so each of the project's source files can import each module.

Now that the module and parition interface files are available the remaining source files can be compiled as usual. They can import and use the components of the the defined modules (and where applicable the defined paritions).

### 25.7.1: Modifying interface units

When module/partition interface units are modified components are added, removed, or altered. E.g., an interface unit may declare a class which is modified: the ordering of its data members may change, new data members may be added, existing data members may be removed.

When a module interface unit is modified and it's recompiled then the modified definition replaces the old one. Consider this interface unit:

        export module Demo;
        export
        {
            class Demo
            {
                int d_value = 100;
                public:
                    int value() const;
            };
        }

The member function `Demo::value` (returning `d_value`) is implemented in its own source file, and is called by `main`:

        import Demo;
        import <iostream>;

        using namespace std;

        int main()
        {
            Demo demo;
            cout << demo.value() << '\n';
        }

When the program is run it outputs 100. Now the module interface unit is modified: `d_first` is added to the class as its first data member:

        export module Demo;

        export
        {
            class Demo
            {
                int d_first = 13;
                int d_value = 100;
                public:
                    int value() const;
            };
        }

Next `moddemo.cc` and `main.cc`, are recompiled and the three object files are linked constructing the binary program. The new binary outputs 13: `value's` object file returns the first bytes of the `Demo` object as an `int`, but since the class `Demo` was modified those bytes no longer contain the value 100.

Such complications are familiar: when using a traditional header declaring a class and the class changes the organization of its data members then in practice all source files using the class must be recompiled (and recursively: if another class is derived from, or contains a data member of the modified class then all source files using the other class must also be recompiled). When using modules such recompilations are also required. The icmodmap(1) support program has an option to recompile module (partition) interface units depending on modified interface units and either to modify the last write times of source files using those modules or to write their names to a file so a build utility can recompile those module using source files.

### 25.7.2: External modules

Modules can import module-compiled system header files (cf. section 25.3.1) and/or module-compiled header files of locally developed libraties (cf. section 25.3.2).

What if a library's design merely uses modules? In that case the library must make available its module-compiled interface files (i.e., `.gcm` files) to its users. Copying the library's `.gcm` files to the `gcm.cache` sub-directory of a using project is not necessary (and probably a bad design anyway, since modifications of the library's `.gcm` files will not be noted), but soft-links should be used. However, often modules import other modules or partitions, and consequently such library-modules in turn may depend on other modules (or partitions). When a project must import a library's module not only the module's `.gcm` file must be available but also (recursively) the module/partition `.gcm` files that module depends on.

As an illustration consider the situation where a project defines three modules: `Module1, Module2,` and `Module3. Module1` imports `External`, which is a module offered by some library; `Module2` imports `Module1`, and `Module3` imports `Module2` (cf. figure 37).

Figure 37: Three modules and an external module

The `External` module doesn't belong to the current project, and so the `External.gcm` file lives elsewhere. When constructing the project its `gcm.cache` directory must make `External.gcm` available. This is realized by defining a soft-link to the actual location of `External.gcm`. But in addition soft-links to the modules/partitions imported by `External.gcm` must be made available in the project's `gcm.cache` sub-directory.

The icmodmap(1) support program can be used to determine and to satisfy the requirements of externally defined modules. To determine the modules' dependencies `icmodmap` is called in the project's top-level directory specifying its `--dependencies` (or `-d`) option. It shows the dependencies amount the modules and reports an error as the module `External` isn't found:

        [Error 1] 1 UNKNOWN module
        Dependencies:
           LOCAL module Module1
               imports UNKNOWN module External
           UNKNOWN module External
           LOCAL module Module2
               imports LOCAL module Module1
           LOCAL module Module3
               imports LOCAL module Module2

And indeed, there's an error: the `External` module wasn't developed in the context of the current project. It's defined in an external library, offering its module/partition compiled interface units to its users. By informing `icmodmap` where the external `.gcm` files are located the error is solved. The relative or absolute path to the directory containing the library's `.gcm` files is either specified as a command-line option or it's specified in a file. Either of these can be passed to `icmodmap` using its `--extern` (or `-e`) option. E.g., if the library's `.gcm` files are in `/tmp/library/gcm.cache` then by calling

        icmodmap -d -e /tmp/library/gcm.cache

the error disappears and `icmodmap` reports:

        Dependencies:
           LOCAL module Module1
               imports EXTERN module External
           EXTERN module External
           LOCAL module Module2
               imports LOCAL module Module1
           LOCAL module Module3
               imports LOCAL module Module2

specifying `--extern` also defines the soft-links to the external modules: the project's `gcm.cache` sub-directory now contains the soft-link

        External.gcm -> /tmp/library/gcm.cache/External.gcm

Now that the requirements of the project's module interface files are all satisfied they can be compiled (they are compiled by `icmodmap` if the `-d` option isn't specified), followed by the compilation of the project's remaining source files. Finally, all object files can be linked to the used object files of the external library in the usual way (specifying, e.g., the linker's `-L` and `-l` options).

## 25.8: Design

When designing projects using modules the same approach as used with traditional projects (using headers) can be followed. Some additional conventions are suggested that specifically apply to modules. Filenames are just filenames. In the C++ Annotations following conventions are adopted:

- the names of files containing module- or partition-interface units begin with `mod`, followed by the lower-case module- or partition-names, using `.cc` extensions (e.g. `modgroup.cc`);
- module's source files are in sub-directories having their lower-case module names (e.g., `./group`)
- partitions are defined in sub-directories of their modules' directories. E.g., if the module `Group` is defined in `./group`, than its partiton `Group:Support` is defined in `./group/support`;
- the project's main directory has a sub-directory `gcm.cache`, initially containing a soft-link `usr/` to the system's `/usr` sub-directory allowing source files to import module-compiled system header files (e.g., `import <iostream>;`);
- module or partition sub-directories have a soft-link `gcm.cache` to `../gcm.cache`, so all compiled module- and partition-interface units are available in the (top-level) `gcm.cache` sub-directory.

The compiler writes compiled interface units in their `gcm.cache` sub-directories. The `.gcm` filenames of modules are equal to the names of the modules (e.g., for `Group` it is `Group.gcm`). The filename of a module-compiled partition starts with its module name, followed by a dash (`-`), followed by the partitions's name (e.g., for `Group:Support` it is `Group-Support.gcm`).

To avoid overfilling interface units they should (like class headers) not define components but merely declare them. Their definitions are provided in separate source files, defined in their interface unit's sub-directory, using the familiar the one component, one source file design principle.

### 25.8.1: 'header' and 'frame' files

Modules and partitions usually their components in separate source files. The initial lines of those source files are identical: they specify the module or the partition to which they belong. Since these source files do not include (internal) header files, they may also declare namespaces. E.g., the member implementations of the `Math:Add` partition (cf. section 25.6) all start with

        module Math;
        import :Add;

Since the `Math:Add` partition interface unit declares a `class Add` most or all of its source files implement a member of `class Add`. In these cases it's convenient to have a predefined `frame` file containing the essential elements of its source files. E.g., for `Math::Add` sources this could be

        module Math;
        import :Add;

        using namespace std;

        void Add::()
        {
        }

When implementing a member copy the `frame` to the intended source file, specify the member's name, define its body and maybe change its return type.

- Table of Contents
- Previous Chapter
- Next Chapter