C++(Clang/GCC)非静态类方法获取调用方完整函数签名方案
问题目标
实现C++类的非静态成员方法,获取调用该方法的函数完整签名,效果与调用方本地使用__PRETTY_FUNCTION__宏获取的自身函数签名完全一致。
现状与预期
现有测试代码为MyClass::foo设置默认参数const char* parent = __builtin_FUNCTION(),运行后输出行2仅能得到调用方的短函数名bar,期望输出行2与输出行3格式一致,即获取到完整签名void Space::bar(int)。
限制条件
MyClass::foo不允许定义为静态方法- 无法通过类声明后定义
#define foo() MyClass::foo(__PRETTY_FUNCTION__)这类宏传参的静态方案解决问题
测试代码
#include <iostream> class MyClass { public: void foo(const char* parent = __builtin_FUNCTION()) { std::cout << "1: " << __PRETTY_FUNCTION__ << std::endl; std::cout << "2: " << parent << std::endl; } }; namespace Space { void bar(int notUsedParam){ MyClass myClass; myClass.foo(); std::cout << "3: " << __PRETTY_FUNCTION__ << std::endl; } } int main() { Space::bar(1); return 0; }
当前运行输出
1: void MyClass::foo(const char*) 2: bar 3: void Space::bar(int)
实现方案
直接将默认参数里的__builtin_FUNCTION()替换为__PRETTY_FUNCTION__即可,不需要修改方法的非静态属性,也不需要调整调用方代码、新增包裹宏。
修改后的MyClass定义:
class MyClass { public: void foo(const char* parent = __PRETTY_FUNCTION__) { std::cout << "1: " << __PRETTY_FUNCTION__ << std::endl; std::cout << "2: " << parent << std::endl; } };
修改后运行输出完全匹配预期:
1: void MyClass::foo(const char*) 2: void Space::bar(int) 3: void Space::bar(int)
跨编译器适配说明:GCC、Clang下使用
__PRETTY_FUNCTION__,MSVC编译器下替换为__FUNCSIG__即可,行为完全一致。
原理说明
函数签名相关内置宏的求值规则为:在哪个源码位置完成求值,就返回对应位置的上下文信息。C++标准规定默认参数的求值发生在调用方的调用表达式位置,而非被调用函数的定义位置,因此写在默认参数位的__PRETTY_FUNCTION__会直接捕获调用方的完整函数签名,完全满足需求。
之前使用__builtin_FUNCTION()只能拿到短函数名,是这个内置函数本身的设计特性——它仅返回裸函数名,不包含命名空间、返回值、参数列表等完整签名信息。
内容的提问来源于stack exchange,提问作者Oshio
相关产品推荐
相关产品推荐

