使用用户定义的文字在C ++ 11中有条件地包含?

时间:2013-02-16 21:20:33

标签: c++ c++11

在C ++ 11中,当表格的预处理指令...

#if expr
遇到

...,expr被评估为constant-expression,如16.1 [cpp.cond]中所述。

expr上进行宏替换后,将其标识符(和关键字)替换为0,将其preprocessing-tokens转换为tokensdefined运算符进行评估等等。

我的问题是当expr中的某个令牌是user-defined-literal时会发生什么?

用户定义的文字与函数调用类似,但函数调用不能在expr(我认为)中发生,作为标识符替换的副作用。但技术上user-defined-literals可以存活下来。

我怀疑这是一个错误,但我不明白如何从标准中得出结论?

或许忽略了在第16条[cpp]上添加用户定义文字的(迂腐)影响?

或者我错过了什么?

更新

通过一个例子澄清:

这预处理的内容是什么:

#if 123_foo + 5.5 > 100
bar
#else
baz
#endif

bar或baz还是错误?

GCC 4.7报告:

test.cpp:1:5: error: user-defined literal in preprocessor expression

所以它认为这是一个错误。这可以参考标准来证明吗?或者这只是“隐含的”?

2 个答案:

答案 0 :(得分:3)

  

在C ++ 11中遇到格式为#if expr ...的预处理指令时,   如expr中所述,constant-expression被评估为16.1 [cpp.cond]

     

这是在expr上进行宏替换后完成的,其标识符(和关键字)是。{   由0替换,其preprocessing-tokens转换为tokens,   评估defined运算符,依此类推。

     

我的问题是当tokens中的一个expr是a时会发生什么   user-defined-literal

该计划格式不正确。

我的观点的核心是从16.1/1脚注147中的观察中收集到的,在翻译阶段4中除了宏名称之外没有identifiers

论据:

根据2.14.8 [lex.ext]/2

  

user-defined-literal被视为对literal operator的调用   或literal operator template (13.5.8)

所以在这里,即使在16.1/4中描述的所有替换之后,我们仍然有一个(运算符)函数的剩余调用。 (其他尝试,例如使用constexpr函数,会被identifiers替换所有非宏0而受阻。)

正如在翻译阶段4中发生的那样,还有没有定义或甚至声明的函数;尝试查找literal-operator-id必须失败(请参阅16.1/1中的脚注147以获得类似的参数)。

从一个略微不同的角度来看,5.19/2我们发现:

  

conditional-expression除非是core constant expression   涉及以下之一作为潜在评估的子表达式   (3.2)[...]:

     
      
  • [...]
  •   
  • 为文字类或constexpr函数调用constexpr构造函数以外的函数;
  •   
  • 调用未定义的constexpr函数或未定义的constexpr构造函数[...];
  •   

由此,在user-defined literal中使用constant expression需要定义的 constexpr literal operator,这又可以'在翻译阶段4可用。

gcc拒绝这一点是正确的。

答案 1 :(得分:0)

  

在C ++ 11中遇到#ifdef expr形式的预处理指令时,expr被评估为16.1所述的常量表达式。这是在expr上的宏替换之后,其标识符(和关键字)被替换为0,其预处理标记被转换为标记,定义运算符被评估,等等。

没有!

#ifdef#ifndefdefined的参数评估。例如,假设我从未#define预处理器符号SYMBOL_THAT_IS_NEVER_DEFINED。这完全有效:

#ifdef SYMBOL_THAT_IS_NEVER_DEFINED
code
#endif

扩展未定义符号的符号是非法的。假设SYMBOL_THAT_IS_NEVER_DEFINED尚未定义,这是非法的:

#if SYMBOL_THAT_IS_NEVER_DEFINED
code
#endif

类似于在解除引用之前检查指针是否为非空,在使用之前检查符号是否合法是合法的:

#if (defined SYMBOL_THAT_MIGHT_BE_DEFINED) && SYMBOL_THAT_MIGHT_BE_DEFINED
code
#endif