模块声明必须是文件首行非注释内容,export module语句唯一且大小写敏感;导出需显式加export;import必须位于翻译单元最前;构建系统须显式支持模块接口文件生成与引用。

module声明必须是文件第一行非注释内容
编译器会直接拒绝任何把export module写在空行、注释之后,或者混在#include或#define后面的文件。这不是警告,而是硬性语法错误:error: module declaration not at global scope。
-
export module math;必须是.ixx或.cppm文件里真正第一行(跳过空白和//注释) - 不能写成
exported module math;或module export math;——export必须紧贴module前 - 模块名大小写敏感,
import Math;和export module math;不匹配 - 一个文件只能有一个
export module语句,重复写会报错
导出符号必须显式加export,不是定义了就能用
export不是修饰符开关,而是精确控制可见性的动作。哪怕函数写在export module文件里,没加export前缀,导入后就完全不可见——error: 'add' was not declared in this scope是典型表现。
-
export int add(int a, int b) { return a + b; }✔️ -
int helper() { return 42; }❌(仅本模块内可用) -
export namespace math { export const double PI = 3.14159; }✔️(export需逐层作用) - 模板定义天然
inline,可放心export template<typename t> T max(T a, T b);</typename> - 全局变量必须加
inline:例如export inline int counter = 0;,否则ODR违规
import语句位置和顺序有硬约束
import不是#include的语法糖,它必须出现在翻译单元最前面,在任何#include、using、变量声明甚至空行之前。否则GCC/Clang会警告或拒绝,MSVC可能静默失败。
-
import math;✔️(文件首行) -
#include <iostream></iostream>import math;❌(#include后不允许import) - 不能在头文件(
.h)里写import——模块不能被#include传播 - 标准库模块如
import <vector></vector>目前仅MSVC部分支持,GCC 13+有限支持<vector></vector>和<string></string>,Clang仍不稳定 -
import不接受路径:import "math.ixx"或import <math.h></math.h>都是非法的
构建系统必须显式处理模块二进制接口文件
模块不是“开个编译器flag就能跑”的功能。每个编译器生成的模块接口文件(MSVC的.ifc、Clang的.pcm、GCC的.gcm)互不兼容,且必须先于依赖它的源文件编译完成。CMake 3.28+才提供实验性支持,多数项目仍需手写规则。
- MSVC:先用
cl /std:c++20 /experimental:module /interface math.ixx生成math.ifc,再用/reference math.ifc编译主文件 - Clang:分两步,
clang++ -x c++-system-header -std=c++20 -fmodules -emit-module-interface -o math.pcm math.ixx,然后主文件编译加-fprebuilt-module-path=. - GCC:需
-fmodules-ts,且当前不支持模块分区(module :private),也不推荐用于生产 - CMake中要设
set_source_files_properties(math.ixx PROPERTIES LANGUAGE CXX),否则会被当普通C++源码忽略 - 模块名解析不依赖文件路径,而靠编译器索引的BMI(Binary Module Interface)——
import math;失败时,大概率是.ifc/.pcm根本没生成或路径没对上
import静默失败,而不是报错。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











