我知道预定义标识符__func__
使函数名可用于函数内。但我什么时候需要呢?其中一个目的可以是调试。其他用例有哪些?
答案 0 :(得分:7)
更新:为了清楚起见,因为在(便携式)C或C ++中,您无法使用当前函数的名称作为“string”(char
数组),几乎只限于在某处编写该字符串 - 这些都可以被视为诊断或“调试”目的。话虽如此,您可能想要为函数名称提供某种用法。例如,声明性安全性,可配置日志记录(虽然再次是“诊断”等)。
事实上,网上的大多数描述和手册都明确提到__func__
和(__LINE__
和__FILE__
的效用)是调试和诊断。
就我个人而言,我认为这是为了帮助“更好”assert()
输出。
只要您“以编程方式”需要知道当前函数的名称,就可以使用它。几乎排除调试器,你可以通过调试器的方式获得当前函数的名称(甚至是上下文)。
__func__
(或其较旧的非标准前任__FUNCTION__
)通常与__LINE__
和__FILE__
宏一起使用,以提供跟踪或诊断输出功能,它自动包含当前函数(和文件,行)。
#define TRACE(s) \
do { fprintf(stderr, "%s:%d:%s: %s", __FILE__, __LINE__, __func__, (s)); \
} while (0)
然后您可以像这样使用它:
int my_func(char* arg1, int arg2)
{
TRACE("Doing stuff...");
/* ... */
}
有关更多信息和示例,请参阅this Stackoverflow Q& A。
即使仅出于这样的输出目的,__func__
的可用性也非常有限,因为它只包含函数的“不合格和简单的名称”。这样,对于上面的例子,它只能通过“my_func”。
在C / C ++中,这意味着对于重载函数,您将无法仅通过__func__
的值来区分它们。如果有的话,也不包括class-和/或namespace-name。
编译器通常还提供包含完整功能签名或其他详细信息的非标准变体(GCC(请参阅__PRETTY_FUNCTION__
),Microsoft C/C++(请参阅__FUNCDNAME__
,{ {1}}))。
答案 1 :(得分:2)
我注意到在我的代码中添加此宏以及__FILE__
和__LINE__
可以帮助那些正在阅读我的程序日志的人。它还使得编写日志函数变得更加容易,因为我不需要对这些值进行硬编码,因为编译器会为我处理这些值。
请记住,人们可能无法访问应用程序的源代码,在某些情况下,只有日志跟踪和输出可供他们使用。如果有一种透明的方式让他们知道发生了什么,那就太好了。
答案 2 :(得分:1)
如果它是constexpr
(它应该,但至少在当前的GCC中不是,不幸的话),它可以被散列并用于实现一个非常简单的高效(编译时,无运行时开销)RTTI系统。
它还可以提供更加可用的std::type_info::hash_code
版本,它既不需要链接RTTI,也不允许不同的调用返回不同的值。
标准提供的版本(从C ++ 11开始)明确没有提供这样的保证,除了作为关联容器中的键(例如std::map
)之外,它对任何东西都没用。
给定保证不同的调用(至少是相同的二进制,或至少具有完全相同的定义的类型),它将更加可用,例如,用于序列化。
(是的,我知道散列函数有冲突。是的,理论上这是一个问题。但是,给定合理数量的位(比如64)和合理数量的键(比如几百),它们很少发生,以至于在实践中不会成为问题,而且这不是人们无法验证的。)