如何使“this”指针常量表达式?

How to make `this` pointer constant expression?

提问人:mada 提问时间:9/13/2022 最后编辑:mada 更新时间:9/13/2022 访问量:274

问:

这是我之前的后续问题:为什么成员函数返回的非静态数据成员不是核心常量表达式?

该问题中提到的示例的简化版本是:

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]),将计算以下值之一:EE

  • (5.1) ([expr.prim.this]),但作为thisconstexprE;

据我所知,表达式是并且它计算,因为返回一个非静态成员。但这属于“例外”部分:成员函数是 constexpr 函数,作为 的一部分进行计算。如果我解析正确,我期望是常量表达式和断言成功。Es.f()thiss.f()this->xs.S::f()s.f()s.f()

但是,此项目符号没有指定必须是常量表达式的要求。我不明白为什么声明为编译程序,即使没有要求,在这个项目符号中定义,是.ssconstexprsconstexpr

我只是在我的示例中应用了措辞,但除非我缺少任何其他规则,否则我看不到这里需要的措辞。(5.1)constexpr

C++ 语言律师 这个 常量表达式

评论

0赞 StoryTeller - Unslander Monica 9/13/2022
您指的是 C++17 草案,您是否特别对 C++17 透视图感兴趣?
0赞 StoryTeller - Unslander Monica 9/13/2022
顺便说一句,那里有更多的子弹。真正的罪犯在名单的后面。
0赞 apple apple 9/13/2022
你是在具体询问措辞吗?因为它是合理的,所以任何参数(包括这个参数)都需要 constexpr 来评估 constexpr 结果。
0赞 mada 9/13/2022
@StoryTeller-UnslanderMonica - 措辞有意义不同吗?
2赞 Eljay 9/13/2022
s不是 constexpr。正如编译器错误所指示的那样。

答:

7赞 Ben Voigt 9/13/2022 #1

因为执行左值到右值的转换,所以整个 kaboodle 不是一个核心常量表达式:return x;

表达式 E 是一个核心常量表达式,除非按照抽象机器的规则 ([intro.execution]) 对 E 的计算将计算以下值之一:

左值到右值的转换应用于 ,这通常是被禁止的,并且不允许这样做的例外情况都不适用。this->S::x

如果 (解析为 ) 是在常量表达式中可用的对象,则更相关的例外适用。但只有当对象在常量表达式中可用时,才会如此:xthis->S::xstruct S

这要求它具有潜在的恒定性:

并且不是潜在的恒定的。因此,它在常量表达式中不可用,它的子对象也不可用。S s{};


回答标题问题,不是一个核心常量表达式,因为它是一个具有自动存储持续时间的对象的地址;该地址可能会在运行时更改。这与问题代码中的完全无关:作为常量指针值对于指针“在常量表达式中可用”既不是必要的,也不是充分的,这反过来又不足以使通过指针找到的对象在常量表达式中可用。thisstatic_assertthis

评论

0赞 doug 9/13/2022
是的,几乎需要向代码声明才能工作。sconstexpr S s{};
0赞 Eljay 9/13/2022
@John • 将(运行时对象,而不是 constexpr)更改为 。由于这是一个运行时对象,我不明白编译器如何使编译时常量表达式有意义。S s{};S s{false};
0赞 mada 9/13/2022
@Eljay - 至少据我所知,更改为什么也没做。S s{};S s{false};
0赞 Eljay 9/13/2022
@John • 该对象是运行时对象。不能将其用作编译时对象。在编译时,编译器无法深入了解对象的状态。(如果你不明白这一点,这就是 Ben 在他的回答中所说的,你为什么接受这个答案?sconstexpr
1赞 Ben Voigt 9/13/2022
@Eljay:指向它的指针(例如在其成员函数中)不必在常量表达式中可用,即为核心常量表达式。例如,任何全局对象在链接时都有一个固定的地址,因此指向此类对象的指针是核心常量。但是指针是恒定的与这里完全无关,它既不必要也不充分。sthis&sstatic_assert