如何让GCC/Clang输出含隐式定义函数的类完整声明?
首先明确结论:GCC和Clang都没有和-E(输出预处理后源码)逻辑完全一致的选项,可以直接输出补全所有隐式成员后的C++源码形式类定义。隐式成员是编译器在语义分析阶段生成的内部中间表示,不会反向渲染成原生C++源码输出,但可以通过以下几种方式拿到完整的隐式成员信息:
方法1:使用Clang的AST转储功能(最直观)
Clang自带-ast-dump编译选项,可以输出编译单元的完整抽象语法树,所有编译器隐式生成的类成员都会被明确标记。针对你给出的空Test类示例,执行命令:clang++ -cc1 -ast-dump test.cpp
输出内容中Test类对应的AST节点下,会完整列出所有隐式生成的特殊成员:默认构造函数、拷贝构造函数、移动构造函数、拷贝赋值运算符、移动赋值运算符、析构函数,每个隐式成员都会携带implicit标识,你可以直接看到每个成员的准确函数签名。
如果觉得全量AST输出冗余,可以加-ast-dump-filter=Test参数,只过滤输出和Test类相关的节点,精简输出内容:clang++ -cc1 -ast-dump -ast-dump-filter=Test test.cpp方法2:使用GCC的类层次转储功能
GCC没有直接输出类AST结构的前端选项,但可以通过-fdump-class-hierarchy参数生成类的完整成员与布局信息文件,执行命令:g++ -fdump-class-hierarchy test.cpp
命令执行后会在当前目录生成.class后缀的转储文件,文件中会列出Test类的所有成员,包括隐式生成的特殊成员函数,同时会标注每个成员的函数签名、类的内存布局偏移信息。方法3:触发编译错误输出成员列表(通用取巧方案,GCC/Clang均适用)
如果你只想快速确认类的所有隐式成员签名,可以写一段故意触发编译错误的代码,让编译器在错误提示中列出类的全部可见成员。示例代码:
class Test {};
int main() {
// 故意调用类中不存在的成员,触发编译错误
Test t;
t.__get_all_implicit_members();
}
编译时编译器会报错提示`__get_all_implicit_members`不是`Test`的成员,同时会在错误信息后附`Test`类的所有可用成员列表,所有隐式生成的特殊成员都会完整列在其中。 > 补充说明:编译器隐式生成的特殊成员函数,只有在代码中实际被ODR使用(满足一次定义规则的使用要求)时,才会生成实际的可执行函数定义,否则仅在语义层面存在声明,不会生成对应的实现代码。 内容的提问来源于stack exchange,提问作者DailyLearner

