截止到C++20标准正式发布,std模块还没能成为标准库的一部分。C++23标准有望将其吸纳到标准库中。
std模块的价值在于,只需要象下面这样一个单条语句:
xxxxxxxxxx
11import std;
就可以使用标准库中的所有组件,而不必再象以前那样,单独包含声明不同组件的一个个头文件:
xxxxxxxxxx
71
2
3
4
5
6
7...
部分标准库组件将其中的名字倾倒进全局命名空间中,例如<cmath>中的sqrt函数。std模块不会这样做,但如果有人还是希望以全局名字的方式使用这些组件,可以导入std.compat模块。将其与std模块分开,既可以避免打乱原有的代码库,还可以提高模块的编译速度。
注意,模块通常不会导出宏,如果需要使用宏,还是要通过“#include”包含相应的头文件。
模块和头文件可以共存,前提是所导入的模块和所包含的头文件,不能存在一致性冲突。这在将大型代码库,从包含头文件,过渡到导入模块的过程中,是必不可少的。
如果所用的实现已经有了一个现成的std模块,它目前可能被标记为“实验性”的,甚至可能还需要一些特殊的选项和设置,但无论如何,直接使用它就好了。Visual C++ 2022提供了许多实验性的模块,为了使用它们,可以象下面这样定义std模块:
xxxxxxxxxx
71export module std;
2
3export import std.regex; // <regex>
4export import std.filesystem; // <filesysm>
5export import std.memory; // <memory>
6export import std.threading; // <atomic>、<condition_variable>、<future>、<mutex>、<shared_mutex>、<thread>
7export import std.core; // 其它所有
显然,这里必须使用C++20编译器,并设置选项以访问这些实验性的模块。请注意,所有实验性的东西都可能随着时间而发生变化。
如果所用的实现还不支持模块,或者还没有提供std模块及其等价物,那么至少还可以回退到包含头文件的时代。它们不仅是标准的,而且是普遍可用的。问题在于,必须先弄清楚所要用到的东西是由哪个头文件提供的。之后,再将对所有用到的标准库头文件的包含,集中放在一个名为“std.h”的总头文件中:
xxxxxxxxxx
91// std.h
2
3
4
5
6
7
8
9...
使用这些标准库组件时,只需象下面这样:
xxxxxxxxxx
11
这样做的问题是,如果在“std.h”头文件中包含的头文件比较多,会严重拖慢编译速度。
解决这个问题的方案之一是象下面这样:
xxxxxxxxxx
161module;
2
3
4
5
6
7
8
9...
10
11export module std;
12
13export istream;
14export ostream;
15export iostream;
16...
还有一种更快捷的方式也能达到同样的目的:
xxxxxxxxxx
91export module std;
2
3export import "iostream";
4export import "string";
5export import "vector";
6export import "list";
7export import "memory";
8export import "algorithms";
9...
其中形如import "iostream"的写法,意指将指定的头文件单元直接导入进来。这其实是一种介于包含头文件和导入模块之间的折中方案。它接受头文件,并将其变为类似模块的东西。它甚至可以将名字注入全局命名空间(如包含头文件)并泄漏宏。
编译它,不会象直接包含头文件一样慢,但也不如导入正经模块那么快。
优先使用实现提供的模块
使用模块
优先使用命名模块而非头文件单元
要使用C标准中的宏和全局名字,请导入std.compat模块
避免使用宏