__func__ 仅提供函数名字符串,不含参数、返回值及限定符;__PRETTY_FUNCTION__ 提供带类型信息的完整签名但属编译器扩展,二者均非运行时可反射的真实签名,无法用于泛型分发或序列化。

直接说结论: __func__ 只给函数名(字符串字面量),__PRETTY_FUNCTION__ 给带类型信息的完整签名(但非标准、GCC/Clang 特有),两者都不是运行时可反射的“真实签名”,别指望靠它们做泛型分发或序列化。
为什么 __func__ 不能当函数签名用
它只是编译器在函数作用域内自动定义的 static const char[],内容仅是纯函数名(不含参数、返回值、const/volatile 限定符):
void foo(int x) {
std::cout
- 在模板中展开后仍是模板名,比如
template里void bar(T) {} __func__永远是"bar" - 重载函数无法区分:
void f(int)和void f(double)的__func__都是"f" - 它是字面量,地址固定,不能用于
constexpr if分支判断类型
__PRETTY_FUNCTION__ 能拿到什么、不能拿什么
这是 GCC 和 Clang 提供的扩展,内容含返回类型、参数列表、模板实参甚至 noexcept,但行为不统一:
template<typename t> auto baz(T t) -> decltype(t+1) {
std::cout
</typename>
- 不是标准 C++,MSVC 完全不支持(会报错或空字符串)
- 内容格式随编译器版本变:Clang 15+ 在 lambda 中可能包含匿名类名,GCC 可能省略默认模板参数
- 仍为字符串字面量,无法在编译期解析成类型;
std::is_same_v这种事它帮不上 - 若函数内联进其他 TU,
__PRETTY_FUNCTION__值取决于调用点所在 TU 的上下文,不稳定
真要获取可编程的“签名”,得换思路
想在编译期区分不同重载或模板实例?靠字符串没用,得用类型系统本身:
- 用
decltype+std::declval获取调用表达式的类型:using sig = decltype(foo(std::declval())); - 对函数指针取址:
auto ptr = static_cast—— 类型明确,但需手动写签名(&foo); - 结合
std::source_location(C++20)记录函数位置,再配合调试符号(如 DWARF)外部解析,这才是生产环境查签名的正路 - 若为日志/诊断,可封装宏:
#define LOG_SIG() std::cerr ,但别把它当类型依据
真正麻烦的地方在于:你看到的字符串只是编译器“好心”给你打印的快照,不是类型系统的组成部分。想靠它做类型安全的事,等于用 printf 的输出去 reinterpret_cast。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











