私有模块片段(module : private;)是c++26中用于在模块接口单元内声明仅本编译单元可见的辅助符号的机制,必须位于export module x;之后、首个export声明之前,不参与abi或导入可见性,不可被其他模块访问,也不能包含import或export。

私有模块片段(private module fragment)不是用来隐藏实现细节的“访问控制机制”,而是让模块接口单元(module interface unit)能引用仅在当前编译单元内有效的辅助声明——它不对外暴露,也不参与模块接口的 ABI 或导入可见性。
private module fragment 的真实作用场景
当你需要在 module interface unit 中使用某些类型、函数或宏,但又不希望它们出现在模块的公开接口中(比如仅用于辅助模板实例化、SFINAE 检测、或内部 constexpr 计算),就可以把它们放进 private module fragment。
- 它只对当前模块文件有效,其他任何
import该模块的代码都看不到里面的内容 - 它不能出现在
module implementation unit中,只能紧接在export module X;后、首个export声明前 - 它不支持
export,所有声明默认为 internal linkage(即使没写static)
语法结构和必须遵守的顺序
private module fragment 的位置和格式非常严格:必须是 module interface unit 中的第二条语句(第一是 module; 或 export module ...;),且以 module : private; 开头,后面直接跟非导出声明。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
export module mylib;
module : private;
// 这里可以定义:
struct detail_helper { int x; };
constexpr int magic_v = 42;
template<typename t> constexpr bool is_valid_v = std::is_integral_v<t>;
export
namespace mylib {
// 接口里可以用上面那些,但调用者 import 后查不到 detail_helper 或 magic_v
export int compute(int n);
}</t></typename>
- 错位会报错:
module : private;不能放在export块之后,也不能在import语句之后 - 不能跨文件:每个
module interface unit只能有一个 private module fragment,且不能拆到多个文件 - 不能 import 其他模块:private fragment 内不允许出现
import,否则编译器会拒绝
常见误用与编译错误
最典型的错误是把它当成 “private 接口” 或 “模块内的 static 封装” 来用,结果发现符号未定义、ODR 违反,或链接失败。
-
undefined reference to 'mylib::detail_helper::detail_helper()':你在 private fragment 定义了非内联函数,又在 export 函数里返回/传入该类型 —— 必须确保所有函数体都在头文件式上下文中定义(如inline或完整定义在 private fragment 内) -
error: 'module : private' must appear before any export declaration:把module : private;写在了export namespace {...}后面 -
error: module declaration not allowed in private module fragment:在 fragment 里写了另一个export module或module; - 试图在另一个
module implementation unit里访问 private fragment 中的名称:不行,它只对当前 TU 生效
替代方案比你想象中更常用
大多数想“隐藏实现”的需求,其实更适合用 module implementation unit + export 接口分离,而不是硬塞进 private module fragment。
- 如果你有一大堆工具函数、辅助类、中间类型——把它们移到
mylib_impl.cppm(implementation unit),只在 interface unit 中export最终 API - private fragment 更适合极小范围的“胶水代码”:比如一个仅用于
export template特化的struct,或一个仅被单个constexpr函数调用的consteval辅助函数 - Clang 和 MSVC 对 private fragment 的诊断差异较大;GCC 13+ 支持尚不稳定,建议先确认工具链版本是否真正启用 C++20 Modules 完整支持
真正容易被忽略的是:private module fragment 中的名称不会进入模块的二进制接口描述,但它会影响编译时的模板实例化行为——哪怕只是多了一个未使用的 concept,也可能让不同 TU 对同一模板的实例化产生分歧。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










