在 C++11 中使用用户定义的文本的条件包含

Conditional inclusion in C++11 with user-defined literal?

本文关键字:文本 条件 包含 定义 用户 C++11      更新时间:2023-10-16

在 C++11 中,当预处理指令

的形式...
#if expr

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

这是在expr上的宏替换之后完成的,其标识符(和关键字(替换为 0,其preprocessing-tokens转换为 tokens,计算defined运算符,等等。

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

用户定义的文字就像函数调用,但函数调用不能发生在expr(我认为(,这是标识符替换的副作用。 然而,从技术上讲,user-defined-literals可以生存下来。

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

也许在第 16 条中添加用户定义的文字的(迂腐(影响被简单地忽略了[cpp]

还是我错过了什么?

更新:

通过一个例子来澄清:

这预处理什么:

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

酒吧还是巴兹还是错误?

GCC 4.7 报告:

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

所以它认为这是一个错误。 参照标准,这能证明是合理的吗? 或者这只是"隐含"?

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

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

我的问题是,当expr中的tokens之一是 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 函数,将被替换为 0 来阻止所有非宏identifiers

由于这发生在翻译阶段 4,因此还没有定义甚至声明的函数;尝试查找literal-operator-id必须失败(有关类似的参数,请参见16.1/1中的脚注 147(。

从稍微不同的角度看,看看5.19/2我们发现:

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

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

因此,在constant expression中使用user-defined literal需要一个定义的constexpr literal operator,这在翻译阶段 4 中同样不可用。

海湾合作委员会拒绝这一点是正确的。

在 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