PAYATHON 2026

C++ modules 中 global module fragment 与 extern "C++" 有何区别?

数据小许

结论

在 module unit 中,#include 应放在 global module fragment 中。extern "C++" 块不能替代它。虽然块内的声明会附属于 global module,但在块内包含头文件仍不符合标准要求。

两种写法的区别

Global module fragment 由 module; 引入,位置在 module declaration 之前。它用于提供附属于 global module、可供该 module unit 使用的声明:

module;
#include <iostream>
export module A;

extern "C++" 是 linkage specification。标准规定,其中的声明附属于 global module。因此,把头文件展开到这个块中,看起来也可能避开命名模块附着问题:

export module A;
extern "C++" {
#include <iostream>
}

不过,标准还单独规定:在 module unit 中,头文件只能在 global module fragment 中包含。extern "C++" 不会将所在位置变成 global module fragment,所以后一种写法不符合这项要求。标准注明这项要求无需诊断,编译器不一定会报错或警告。C++ 工作草案:模块规则、头文件包含要求

推荐写法

将头文件放在 module; 和 module declaration 之间:

module;
#include <iostream>
export module A;

export void print_message() {
    std::cout << "Hello\n";
}

模块声明之后的声明位于 module purview。global module fragment 中可用的声明也可供该 module unit 使用,但其可见性和可达性仍受模块规则约束。不要因为某个编译器接受这种写法,或很少发出警告,就用 extern "C++" 块包住 include。

注意事项

这里的结论针对问题中的头文件包含方式。extern "C++" 用于指定语言链接属性;global module fragment 则用于安排模块单元中的声明附着和头文件包含位置。最新在线 C++ 工作草案仍保留上述头文件包含限制。若改用 header unit,应根据目标编译器及其对相应 header unit 的支持情况单独处理。

备注:内容仅供参考。