以下代码在 GCC 和 MSVC 上编译,但被 Clang 拒绝:
struct X
{
const void *p_;
consteval X()
: p_{this}
{
}
};
static constexpr X x{};
(https://godbolt.org/z/ExYMeTcTq)
Clang 这里正确吗?
我的理解是
x{}
是构造函数的立即调用,并且在其体内 static constexpr
变量的地址应该是已知的常量值。
这个类似问题的答案显示了如何在同一表达式中创建的对象上调用成员函数是有效的,因此我还有一个理由认为
this
在这种情况下也是一个vlid常量。
更让我困惑的是,如果类的构造函数被标记为
constexpr
而不是 consteval
,Clang 会很高兴地接受代码。
该程序结构良好。从expr.const可以看出:
表达式 E 是核心常量表达式,除非对 E 的求值遵循抽象机 ([intro.execution]) 的规则,将求值以下其中一项:
- this ([expr.prim.this]),除了
- 在 constexpr 函数 ([dcl.constexpr]) 中,该函数作为 E 或
的一部分进行计算
下面是一个更人为的示例,其格式良好的原因与您的代码完全相同:
struct X {
int i;
consteval X(int x) {
this->i = x; //valid and compiles in all 3 compilers
}
};
constexpr X s{5};