too*_*ays 4 c++ language-lawyer c-preprocessor
请考虑以下代码,这会导致在true预处理器条件中计算布尔文字:
#define SOME_MACRO true
int main ()
{
#if SOME_MACRO
return 1;
#else
return 0;
#endif
}
Run Code Online (Sandbox Code Playgroud)
Clang 3.4和GCC 4.8都接受这个代码,即使是-pedantic -std=c++11 -Wall -Wextra.
Visual Studio 2013拒绝它,致命错误C1017:无效的整数常量表达式.
我对n3376§16.1的解读是,应该应用用于评估常量表达式的常规C++规则.
如果是这样,这段代码是有效的,如果MSVC不接受它,那就是一个错误.
但我没有发现这种标准特别清楚.有人能证实吗?
是的,它是有效的.参见C++11§16.1/ 4(强调我的)
在评估之前,将替换将成为控制常量表达式的预处理标记列表中的宏调用(除了由
defined一元运算符修改的那些宏名称之外),就像在普通文本中一样.如果defined由于此替换过程而生成令牌,或者defined在宏替换之前使用一元运算符与两个指定表单中的一个不匹配,则行为是未定义的.在由于宏扩展和defined一元运算符执行的所有替换之后,除了true和之外的所有剩余标识符和关键字false都被替换为pp编号0,然后每个预处理标记被转换为标记.得到的标记包括控制常数表达式,其根据5.19的规则使用至少具有18.3中规定的范围的算法来评估.出于此令牌转换和评估的目的,所有有符号和无符号整数类型的行为分别与它们具有相同的表示形式intmax_t或uintmax_t(18.4).这包括解释字符文字,这可能涉及将转义序列转换为执行字符集成员.这些字符文字的数值是否与在表达式中发生相同字符文字时获得的值匹配(在a#if或#elif指令中除外)是实现定义的.此外,单字符字符文字是否可能具有负值是实现定义的.在继续处理之前,每个具有类型的子表达式bool都经过整体提升.