20 std模块

20.1 引言

截止到C++20标准正式发布,std模块还没能成为标准库的一部分。C++23标准有望将其吸纳到标准库中。

std模块的价值在于,只需要象下面这样一个单条语句:

就可以使用标准库中的所有组件,而不必再象以前那样,单独包含声明不同组件的一个个头文件:

部分标准库组件将其中的名字倾倒进全局命名空间中,例如<cmath>中的sqrt函数。std模块不会这样做,但如果有人还是希望以全局名字的方式使用这些组件,可以导入std.compat模块。将其与std模块分开,既可以避免打乱原有的代码库,还可以提高模块的编译速度。

注意,模块通常不会导出宏,如果需要使用宏,还是要通过“#include”包含相应的头文件。

模块和头文件可以共存,前提是所导入的模块和所包含的头文件,不能存在一致性冲突。这在将大型代码库,从包含头文件,过渡到导入模块的过程中,是必不可少的。

20.2 使用你的实现所提供的东西

如果所用的实现已经有了一个现成的std模块,它目前可能被标记为“实验性”的,甚至可能还需要一些特殊的选项和设置,但无论如何,直接使用它就好了。Visual C++ 2022提供了许多实验性的模块,为了使用它们,可以象下面这样定义std模块:

显然,这里必须使用C++20编译器,并设置选项以访问这些实验性的模块。请注意,所有实验性的东西都可能随着时间而发生变化。

20.3 使用头文件

如果所用的实现还不支持模块,或者还没有提供std模块及其等价物,那么至少还可以回退到包含头文件的时代。它们不仅是标准的,而且是普遍可用的。问题在于,必须先弄清楚所要用到的东西是由哪个头文件提供的。之后,再将对所有用到的标准库头文件的包含,集中放在一个名为“std.h”的总头文件中:

使用这些标准库组件时,只需象下面这样:

这样做的问题是,如果在“std.h”头文件中包含的头文件比较多,会严重拖慢编译速度。

20.4 制作你自己的std模块

解决这个问题的方案之一是象下面这样:

还有一种更快捷的方式也能达到同样的目的:

其中形如import "iostream"的写法,意指将指定的头文件单元直接导入进来。这其实是一种介于包含头文件和导入模块之间的折中方案。它接受头文件,并将其变为类似模块的东西。它甚至可以将名字注入全局命名空间(如包含头文件)并泄漏宏。

编译它,不会象直接包含头文件一样慢,但也不如导入正经模块那么快。

20.5 建议