C++20主模块接口单元是否导出间接导入的模块分区?
请看如下示例:
// translation C export module M:C;
// translation U export module M:B; import :C;
// translation unit T export module M; export import :B; // #1 imports `M:B` and `M:C`
标准[module.unit]条款规定:
模块的所有属于模块接口单元的模块分区,应当由主模块接口单元直接或间接导出(见[module.import])。违反该规则时不要求编译器必须给出诊断。
标准[module.import]第7款规定:
当module-import-declaration导入翻译单元T时,它同时会导入T中所有由导出的module-import-declaration所导入的翻译单元;这类翻译单元即被称为由T导出。此外,若模块M的某模块单元中的module-import-declaration导入了M的另一模块单元U,则它也会导入U的模块单元作用域内所有非导出module-import-declaration导入的翻译单元。上述规则可递归生效,进而导入更多翻译单元。
上述规则第一部分表明:若T中的导出module-import-declaration****导入了某翻译单元,则T导出该翻译单元。
由于U中存在非导出的module-import-declaration import :C;,且M的主模块单元中#1处的module-import-declaration导入了M的另一模块单元U,根据上述“此外”起始的附加规则,#1处的module-import-declaration同样会导入C。
进一步,由于T中#1处的module-import-declaration是导出声明,它直接导入M:B、间接导入M:C,因此M:B和M:C均应由T导出。
据此可得出结论:所有分区模块接口单元都已被主模块接口单元导出。但使用GCC执行编译命令g++ -std=c++20 -fmodules-ts c.cpp u.cpp t.cpp时,编译器报错:
interface partition is not exported
核心疑问为:该报错属于GCC的实现bug,还是分区C实际并未被T导出、此处标准规则存在表述不清晰的问题?
更新:
补充如下测试代码:
// file c export module C; export int fun(){return 0;} // file b export module M:B; import C; // file a export module M; export import :B; // #1 int d = fun(); // #2 // file main import M; int main(){}
上述测试示例中#2处的代码是良构的。原因是#1处的导出module-import-declaration不仅导入了M:B,也同时导入了C,因此#2处可以找到函数fun的定义。那么按照标准中“T中导出module-import-declaration所导入的所有翻译单元;这类翻译单元即被称为由T导出”的表述,无法直接解释为何不能认定翻译单元a中#1处导出module-import-declaration所导入的翻译单元C是由a导出的。
T中导出module-import-declaration所导入的所有翻译单元;这类翻译单元即被称为由T导出。
由此可见,尽管GCC的实现行为可能是正确的,但无法从现有标准条文中直接读出对应结论,此处标准表述存在歧义。
内容的提问来源于stack exchange,提问作者xmh0511

