我刚刚注意到__func__
,__FUNCTION__
和__PRETTY_FUNCTION__
并未被视为预处理器宏,并且上未提及它们16.8标准的预定义宏名称部分(N4527 Working Draft)。
这意味着它们不能用于phase 6的字符串连接技巧:
// Valid
constexpr char timestamp[]{__FILE__ " has been compiled: " __DATE__ " " __TIME__};
// Not valid!!!
template <typename T>
void die() { throw std::runtime_error{"Error detected in " __PRETTY_FUNCTION__}; }
据我所知,__FILE__
,__DATE__
和__TIME__
已转换为标准所述的字符串文字:
标准提到16.8预定义的宏名称[cpp.predefined]
__DATE__
源文件的翻译日期:{strong>字符串文字
"Mmm dd yyyy"
,其中月份的名称与asctime函数生成的月份名称相同,并且如果值小于10,则dd的第一个字符是空格字符。如果翻译日期不是 可用,应提供实施定义的有效日期。
__FILE__
当前源文件的假定名称(字符串文字)。
__TIME__
源文件的翻译时间:形式为
"hh:mm:ss"
的字符串文字,与asctime函数生成的时间一样。
__func__
作为形式的函数本地预定义变量:
static const char __func__[] = "function-name ";
所以事实是这是一个局部变量,因此字符串连接技巧不适用于它。
至于标准中没有提及__FUNCTION__
和__PRETTY_FUNCTION__
(实现定义了吗?),但认为它们的行为类似于__func__
是一个相当安全的选择。
所以问题是:为什么__func__
,__FUNCTION__
和__PRETTY_FUNCTION__
是函数本地静态常量字符数组__FILE__
,__DATE__
和{{ 1}}是字符串文字?这个决定背后的基本原理(如果有的话)是什么?
答案 0 :(得分:27)
在预处理时扩展__func__
需要预处理器知道它正在处理哪个函数。预处理器通常不知道,因为解析在预处理器完成之后发生。
某些实现结合了预处理和解析,在这些实现中,__func__
可以按照您喜欢的方式工作。事实上,如果我没记错的话,MSVC的__FUNCTION__
就是这样的。然而,对于将翻译阶段分开的实现,这是一种不合理的要求。