为什么在模块中导出 std::vector<std::string> 等类型别名允许在某些内部分区中同时使用 std::vector 和 std::string?

Why does exporting a type alias such as std::vector<std::string> in a module allow use of both std::vector and std::string in some internal partition?

我目前正在使用 Visual Studio 2022 更新 17.1.6,我发现导出类型别名很有趣。由于我不明白的原因,当我在模块接口文件中导出某些数据类型(例如 std::vector<std::string> 的类型别名时,我可以在文件中同时使用 std::vector<>std::string导入它。例如:

modInterface.ixx

export module words;
import <iostream>
import <vector>;
import <string>;
...
export using Words = std::vector<std::string>;
...

在内部分区中:

modInternalPartition.cpp

module words:wordsIP;
import words;

//This compiles as expected
Words wordStorage;

//Why does my compiler sees below as correct, and compiles it without error?
std::vector<int> numStorage = { 1, 2, 3, 4 };

//Why does my compiler also sees below as correct, and compiles it without error?
std::string text = "This dish is tasty";

//This would produce an error, which is expected since I did not export import <iostream> in modInterface.ixx
std::cout << text;
...

我的第一个想法是,既然Words是一个类型别名,导出它就意味着导出std::vector<>std::string,但是既然std::vector<>是一个模板,为什么不是只导出它的实例化(std::vector<std::string>)吗?

当模块的一个 部分 导入另一个时,所有不受内部链接影响的声明都可用,就好像它们被 导出 一样。这甚至适用于 import 声明(以及通过其 non-partition 实现单元隐式导入模块),因此 import <vector>; 是在 words:wordsIP 分区中可用。 export 与它完全无关。

关于模块有一件有趣的事情:export 声明只对模块外部 的代码有影响。

如果您导入与您属于同一模块的模块单元,您可以访问该模块单元中的所有 声明。这允许您拥有“私有”声明,这些声明不会导出到模块的接口,但仍然可以被模块中 中的其他代码访问。这个includes module imports:

Additionally, when a module-import-declaration in a module unit of some module M imports another module unit U of M, it also imports all translation units imported by non-exported module-import-declarations in the module unit purview of U.

Header单位在这方面并不特殊。您导入了那些 header 单元,因此它们由您的主模块接口导入。因此,导入您的主模块接口的该模块的任何模块实现都将看到它们。