C++ 为什么函数、函数和漂亮函数是';t预处理器宏?

C++ 为什么函数、函数和漂亮函数是';t预处理器宏?,c++,c-preprocessor,standards,C++,C Preprocessor,Standards,我刚刚注意到,\uuuuu func\uuuu、\uuu FUNCTION\uuuu和\uuu PRETTY\u FUNCTION\uuuu没有被视为预处理器宏,在标准的16.8预定义宏名称部分也没有提到它们() 这意味着它们不能用于以下字符串串联技巧: 事实上,这是一个局部变量,因此字符串串联技巧不能与之配合使用 至于\uuuu FUNCTION\uuuuu和\uuu PRETTY\u FUNCTION\uuuuu,标准中没有提到(是否定义了实现?),但如果认为它们的行为类似于\uuuuu F

我刚刚注意到,
\uuuuu func\uuuu
\uuu FUNCTION\uuuu
\uuu PRETTY\u FUNCTION\uuuu
没有被视为预处理器宏,在标准的16.8预定义宏名称部分也没有提到它们()

这意味着它们不能用于以下字符串串联技巧:

事实上,这是一个局部变量,因此字符串串联技巧不能与之配合使用

至于
\uuuu FUNCTION\uuuuu
\uuu PRETTY\u FUNCTION\uuuuu
,标准中没有提到(是否定义了实现?),但如果认为它们的行为类似于
\uuuuu FUNCTION\uuuuuuu
,这是一个相当安全的赌注


所以问题是:
\uuuu func\uuuu
\uuu FUNCTION\uuuu
\uu PRETTY\u FUNCTION\uuuuu
为什么函数是字符的局部静态常量数组,而
\uu FILE\uuuuu
\uu DATE\uuuuu
\uuu时间\uuuu
是字符串文字?这个决定背后的理由(如果有的话)是什么?

在预处理时扩展
\uuuu func\uuuu
,需要预处理器知道它正在处理哪个函数。预处理器通常不知道这一点,因为解析发生在预处理器已经完成之后


有些实现将预处理和解析结合在一起,在这些实现中,
\uuu func\uu
可以按照您希望的方式工作。事实上,如果我没记错的话,MSVC的
\uuuuuuuu函数
就是这样工作的。但是,对于将翻译的各个阶段分开的实现来说,这是一个不合理的要求。

这比你想象的还要糟糕,它们甚至不是文字。。。如果是,例如,您可以在构造函数中使用
constexpr
函数进行编译时哈希,以获得超级简单、超级廉价的迷你RTTI实现(只适合序列化)。当你尝试时,编译器会告诉你“不是一个常量表达式”。@Damon这是一个非常有趣的观察结果,你有没有一个你描述的行为的例子?我也想自己测试一下,大约一年前我就试过了,因为这似乎是制作RTTI系统的好方法,它的开销是每个类存储一个静态整数。您需要存储一些东西,而构造函数名称(即类名)的compiletime哈希似乎是理想的。一个函数的名称显然也是一个compiletime常量(它实际上没有太多的更改方式,是吗!)。但是GCC不喜欢这个想法,因为
\uuuu func\uuuu
的别名(小写或大写,漂亮或不漂亮)都不是一个常量表达式。如果能看看反射研究小组(SG7)是否有一个解决方案,C++1zI两天来一直认为我不懂预处理器指令,那就太好了。我能想到的最好的替代方法是用存储签名的预处理器定义替换签名,并使用下一行的变量展开签名。在函数内部,可以根据需要对同一变量进行字符串化、连接等操作。我不喜欢预处理器解决方案限制编译器编写代码的方式,所以我愿意接受其他方案。如果您需要C字符串,可以在错误消息中插入sprintf?否则STL?@JohnP,但如何在一个函数与另一个函数之间重写此变量?这难道不会中断一个以上的功能吗?
// 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__}; }
static const char __func__[] = "function-name ";