为什么__func __,__ FUNCTION__和__PRETTY_FUNCTION__不是预处理器宏?

时间:2015-07-15 12:44:31

标签: c++ c-preprocessor standards

我刚刚注意到__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}}是字符串文字?这个决定背后的基本原理(如果有的话)是什么?

1 个答案:

答案 0 :(得分:27)

在预处理时扩展__func__需要预处理器知道它正在处理哪个函数。预处理器通常不知道,因为解析在预处理器完成之后发生。

某些实现结合了预处理和解析,在这些实现中,__func__可以按照您喜欢的方式工作。事实上,如果我没记错的话,MSVC的__FUNCTION__就是这样的。然而,对于将翻译阶段分开的实现,这是一种不合理的要求。