4

考虑示例:

template <char>
struct foo { };

int main() {
    foo<""[0]?""[1]:'\0'>{};
}

代码在[gcc][clang]中都可以编译,但真的应该这样吗?我知道表达式""[1]不需要评估,因为它是短路的。但是标准不是很清楚表达式是否真的可以作为核心常量表达式。相关的 [expr.const]/2尤其是部分:

如果 e 满足核心常量表达式的约束,但对 e 的评估将评估具有未定义行为的操作,如本文档的 [library] 到 [thread] 中指定的,则未指定 e 是否为核心常量表达式。

提出了我的疑问...

4

2 回答 2

6

I believe the extract actually covers that:

If e satisfies the constraints of a core constant expression, but evaluation of e would evaluate an operation that has undefined behaviour as specified in [library] through [thread] of this document, it is unspecified whether e is a core constant expression.

There is actually no undefined behaviour in the expression ""[0]?""[1]:'\0' because the only problematic bit ""[1] is never actually executed. In fact, the entire expression can simply be optimised to '\0' without adverse effects.

The reason it's not executed comes from the standard itself (e.g., C++11 5.16 Conditional operator [expr.cond] /1:

Conditional expressions group right-to-left. The first expression is contextually converted to bool (Clause 4). It is evaluated and if it is true, the result of the conditional expression is the value of the second expression, otherwise that of the third expression. Only one of the second and third expressions is evaluated.

Since ""[0] will always evaluate to false in the boolean context, the second sub-expression is never executed. It's really no conceptually different from the expression:

false ? (1/0) : 42

in that you'll never actually have to worry about the possibility of divide-by-zero.

于 2017-11-27T12:51:06.437 回答
3

要回答这个问题,必须引用本段的开头,它说:

表达式 e 是核心常量表达式,除非按照抽象机的规则对 e 的求值将求值以下表达式之一:

并且由于抽象机的规则承诺不会发生越界访问的评估([expr.cond]/1):

条件表达式从右到左分组。第一个表达式根据上下文转换为布尔值。它被评估,如果为真,则条件表达式的结果是第二个表达式的值,否则是第三个表达式的值。仅计算第二个和第三个表达式中的一个

没有未定义的行为,因此它必须是核心常量表达式。或者至少,不是您引用的子弹取消了它的资格。

于 2017-11-27T13:00:04.617 回答