在常量表达式中不允许读取非 constexpr 变量“p”

问题描述 投票:0回答:1

为什么可以通过对象 's' 直接使用方法 'func()' 来初始化 constexpr 变量('x' 或 'y'),而不是通过指针变量 'p'(对于 'z') ?此外,对象“s”本身以及相应的指针“p”都不是常量表达式。

struct S {
  auto constexpr static size() { return 42; }
  auto constexpr func() const { return 42; }
};

int main() {
  S s;
  auto p{&s};

  auto constexpr x{s.func()};     // OK
  auto constexpr y{(&s)->func()}; // OK
  auto constexpr z{p->func()};    // ERROR

  return 0;
}

我试图根据以下问题来解决这个问题 [1][2],但他们只解决了“constexpr 函数在编译时和运行时可用”。 1 2

c++ static constexpr
1个回答
0
投票

这是关于“动态类型为 constexpr-unknown 的对象”,这是P2280R4引入的概念。该论文有一整节关于允许使用

(&s)->func()
但不允许使用
p->func()
的原因,标题为
nullptr
怎么样?”
.

从机械上讲,这是通过标准中的这一行实现的([expr.const]p9):

在将表达式 E 作为核心常量表达式求值期间,所有引用其生命周期不以 E 求值开始的对象或引用的

id-expressions
*this 的使用均被视为指的是该对象或引用的特定实例,其生命周期和所有子对象(包括所有联合成员)的生命周期包括整个常量评估。

因此

s
p
都具有在不断求值期间 constexpr 未知的动态类型,因此您可以使用它们,但无法访问它们的值。

这意味着

s.func()
没问题,因为
func
无法访问该对象。

p->func()
不是,因为您试图通过隐式取消引用来访问指针。

(&s)
can 在持续评估过程中被取消引用。
&s
不像
p
那样是 constexpr-unknown,并且它的值可以在持续评估期间使用(它只是
s
),所以
(&s)->func()
很好。

© www.soinside.com 2019 - 2024. All rights reserved.