提问人:mada 提问时间:9/13/2022 最后编辑:mada 更新时间:9/13/2022 访问量:274
如何使“this”指针常量表达式?
How to make `this` pointer constant expression?
问:
这是我之前的后续问题:为什么成员函数返回的非静态数据成员不是核心常量表达式?
该问题中提到的示例的简化版本是:
struct S {
const bool x = true;
constexpr bool f() { return x; }
};
int main() {
S s{};
static_assert(s.f()); // error: 's' is not a constexpr;
}
该标准的适用措辞是 N4861:[expr.const]/(5.1):
表达式是核心常量表达式,除非计算 的,遵循抽象机器的规则 ([intro.execution]),将计算以下值之一:
E
E
- (5.1) ([expr.prim.this]),但作为
this
constexpr
E
;
据我所知,表达式是并且它计算,因为返回一个非静态成员。但这属于“例外”部分:成员函数是 constexpr 函数,作为 的一部分进行计算。如果我解析正确,我期望是常量表达式和断言成功。E
s.f()
this
s.f()
this->x
s.S::f()
s.f()
s.f()
但是,此项目符号没有指定必须是常量表达式的要求。我不明白为什么声明为编译程序,即使没有要求,在这个项目符号中定义,是.s
s
constexpr
s
constexpr
我只是在我的示例中应用了措辞,但除非我缺少任何其他规则,否则我看不到这里需要的措辞。(5.1)
constexpr
答:
因为执行左值到右值的转换,所以整个 kaboodle 不是一个核心常量表达式:return x;
表达式 E 是一个核心常量表达式,除非按照抽象机器的规则 ([intro.execution]) 对 E 的计算将计算以下值之一:
非易失性 glvalue,它引用可在常量表达式中使用的对象,或者
文字类型的非易失性glvalue,指其寿命从E的计算开始的非易失性对象;
左值到右值的转换应用于 ,这通常是被禁止的,并且不允许这样做的例外情况都不适用。this->S::x
如果 (解析为 ) 是在常量表达式中可用的对象,则更相关的例外适用。但只有当对象在常量表达式中可用时,才会如此:x
this->S::x
struct S
这要求它具有潜在的恒定性:
并且不是潜在的恒定的。因此,它在常量表达式中不可用,它的子对象也不可用。S s{};
回答标题问题,不是一个核心常量表达式,因为它是一个具有自动存储持续时间的对象的地址;该地址可能会在运行时更改。这与问题代码中的完全无关:作为常量指针值对于指针“在常量表达式中可用”既不是必要的,也不是充分的,这反过来又不足以使通过指针找到的对象在常量表达式中可用。this
static_assert
this
评论
s
constexpr S s{};
S s{};
S s{false};
S s{};
S s{false};
s
constexpr
s
this
&s
static_assert
评论
s
不是 constexpr。正如编译器错误所指示的那样。