我刚刚注意到
这意味着它们不能在第6阶段的字符串连接技巧中使用:
__func__
、__FUNCTION__
和__PRETTY_FUNCTION__
没有被视为预处理器宏,并且它们没有在标准的16.8 预定义宏名称章节中提到(N4527 工作草案)。这意味着它们不能在第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__
源文件翻译的日期:
"Mmm dd yyyy"
形式的字符字面值,其中月份的名称与asctime函数生成的相同,并且如果dd的值小于10,则其第一个字符是空格字符。如果无法获取翻译日期,则应提供实现定义的有效日期。
__FILE__
当前源文件的假定名称(字符字面值)。
__TIME__
源文件翻译时的时间:
"hh:mm:ss"
形式的字符字面值,与asctime函数生成的时间相同。
标准中还提到了__func__
,它是一种函数本地的预定义变量,形式如下:
static const char __func__[] = "function-name ";
事实是这是一个局部变量,因此使用字符串连接技巧无法在其上工作。
至于__FUNCTION__
和__PRETTY_FUNCTION__
没有在标准中提到(是否是实现定义?)但可以放心地认为它们的行为类似于__func__
。
那么问题是:为什么__func__
、__FUNCTION__
和__PRETTY_FUNCTION__
是函数本地静态常量字符数组,而__FILE__
、__DATE__
和__TIME__
是字符串字面值?这个决定背后有什么理由(如果有的话)?
constexpr
函数进行编译时哈希,以获得一个超级简单、成本极低的小型RTTI实现(仅足够用于序列化)。当你尝试这样做时,编译器会告诉你“不是常量表达式”。 - Damon__func__
之类的任何东西(小写或大写,漂亮或不漂亮)都不是常量表达式。 - Damon