核心常量表达式可以包含被忽略的 reinterpret_cast 吗?

Igo*_*r G 0 c++ language-lawyer c++17

使用godbolt.org 在线编译器编译以下示例程序时,Clang-9.0.0 和MSVC v19.24 都在标记为(1)和(2)的行报告错误。错误消息说表达式(reinterpret_cast<uintptr_t>(&x), 1)不计算为常量。但确实如此,不是吗?

另一方面,GCC-9.2 编译这个示例没有错误。

#include <memory>

int x;

enum
{
    Value = (reinterpret_cast<uintptr_t>(&x), 1)    // (1)
};

template <int N>
struct Test
{
};

Test<(reinterpret_cast<uintptr_t>(&x), 1)>     t;   // (2)
Run Code Online (Sandbox Code Playgroud)

问题是:(reinterpret_cast<uintptr_t>(&x), 1)求值为常数吗?

Bri*_*ian 7

核心常量表达式不能包含 a,reinterpret_cast即使其值被丢弃(因此 MSVC 和 Clang 拒绝代码是正确的)。参见 C++17 [expr.const]/2.15:

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

根据抽象机器的规则,reinterpret_cast必须对 进行评估。见[expr.comma]/1:

一对用逗号分隔的表达式从左到右求值;左边的表达式是一个弃值表达式。与左表达式关联的每个值计算和副作用在与右表达式关联的每个值计算和副作用之前排序。...

很明显,仅仅对 求值reinterpret_cast就足以使表达式不是核心常量表达式,即使它根本不影响结果。

这与真正不评估演员表的情况不同:

enum {
    Value = 1 || reinterpret_cast<uintptr_t>(&x);  // OK
}
Run Code Online (Sandbox Code Playgroud)