// mylibrary.cpp
#include "mylibrary.h"
int myfunction()
{
return 123;
}
In our main.cpp file we also include the above header file and call the function:
// main.cpp
#include "mylibrary.h"
int main()
{
int x = myfunction();
}
We include the same header multiple times. This increases compilation time. Modules are included only once, and we do not have to separate the code into interface and implementation. One way is to have a single module file, for example, mymodule.cpp where we provide the entire implementation and export of this function.
To create a simple module file which implements and exports the above function, we write:
// mymodule.cpp
export module mymodule;
export int myfunction() { return 123; }
Explanation: the export module mymodule; line says there is a module called mymodule in this file. In the second line, the export specifier on the function means the function will be visible once the module is imported into the main program.
We include the module in our main program by writing the import mymodule; statement.
// main.cpp
import mymodule;
int main()
{
int x = myfunction();
}
In our main program, we import the module and call the exported myfunction() function.
A module can also provide an implementation but does need to export it. If we do not want our function to be visible to the main program, we will omit the export specifier in the module. This makes the implementation private to the module:
export module mymodule;
export int myfunction() { return 123; }
int myprivatefunction() { return 456; }
If we have a module with a namespace in it, and a declaration inside that namespace is exported, the entire namespace is exported. Within that namespace, only the exported functions are visible Example:
// mymodule2.cpp
export module mymodule2;
namespace MyModule
{
export int myfunction() { return 123; }
}
main2.cpp:
import mymodule2;
int main()
{
int x = MyModule::myfunction();
}
20.2 Concepts
类型总是定义了一组特定的操作。模板实现的泛型有些不能满足特定类型的需要,一种方法是类型特化,concepts的方法是显式声明类型的特定要求。
Remember the class templates and function templates providing generic types T? If we want our template argument T to satisfy certain requirements, then we use concepts. In other words, we want our T to satisfy certain compile-time criteria. The signature for a concept is:
template
concept concept_name = requires (T var_name) { reqirement_expression; };
The second line defines a concept name followed by a reserved word requires, followed by an optional template argument T and a local var_name, followed by a requirement_expression which is a constexpr of type bool.
In a nutshell, the concept predicate specifies the requirements a template argument must satisfy in order to be used in a template. Some of the requirements we can write ourselves, some are already pre-made.
We can say that concepts constrain types to certain requirements. They can also be seen as a sort of compile-time assertions for our template types.
For example, if we want a template argument to be incrementable by one, we will specify the concept for it: