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

A R*_*A R 9 c++ string templates vector c++20

我目前正在使用 Visual Studio 2022 Update 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>;
...
Run Code Online (Sandbox Code Playgroud)

在内部分区中:

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;
...
Run Code Online (Sandbox Code Playgroud)

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

Nic*_*las 3

关于模块,有一个有趣的事情:声明仅对模块外部export的代码起作用。

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

此外,当某个模块 M 的模块单元中的模块导入声明导入 M 的另一个模块单元 U 时,它还会导入由 U 的模块单元权限中的非导出模块导入声明导入的所有翻译单元。

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