[expr.const] 部分中“前面的初始化”一词的含义是什么

jac*_*k X 5 c++ language-lawyer constant-expression c++17

constexpr int func(int const& rf){
    return rf;
}
int main(){
   constexpr int value = func(0);
}
Run Code Online (Sandbox Code Playgroud)

考虑上面的代码,变量value应该由一个常量表达式初始化,即func(0),它首先应该是一个核心常量表达式。为了判断表达式是否func(0)是核心常量表达式,将应用以下规则,即:
expr.const#2.7

表达式 e 是核心常量表达式,除非对 e 的求值遵循抽象机的规则,将求值以下表达式之一:

左值到右值的转换,除非它应用于

[...], 或者

(2.7.4) 文字类型的非易失性泛左值,指的是其生命周期开始于 e 求值期间的非易失性对象;

尽管lvalue-to-rvalue conversion应用了rf并且这种转换满足了要点(2.7.4),但是,请看一下下一段,即:
expr.const#2.11

引用引用类型的变量或数据成员的 id 表达式,除非引用具有前面的初始化并且

  • (2.11.1) 它用常量表达式初始化,或者,
  • (2.11.2) 其生命周期开始于 e 的评估内;

我不知道这句话的真正preceding initialization含义是什么?这是否意味着变量应该在使用之前进行初始化,或者意味着在变量的声明中应该有一个初始值设定项。无论如何,在将 应用于lvalue-to-rvalue conversion glvalue之前rf,应该评估 glvaluerf以确定对象的身份,该身份由以下规则决定:

左值是一个表达式,其计算确定对象、位域或函数的标识。

这意味着不仅应遵守项目符号 [expr.const#2.7],还应遵守 [expr.const#2.11]。

因为 id-expressionrf是引用类型。因此,为了使表达式func(0)成为核心常量表达式,id-表达式rf必须有一个前置的初始化,并且至少满足bullet(2.11.1)和(2.11.2)之一。在我的示例中,遵循项目符号 (2.11.2),rf并且编译器同意这func(0)是一个常量表达式。结果在这里,结果似乎证明这preceding initialization意味着be initialized而不是有一个初始值设定项,因为参数声明在第一个示例中没有初始值设定项。

为了验证这样的想法,我测试了以下代码:

constexpr int func(int const& rf){
    constexpr int const& v = rf;  
    return 0;
}
int main(){
   static int const data = 0;
   constexpr int value = func(data);
}
Run Code Online (Sandbox Code Playgroud)

编译器指出的结果不是rf常量表达式。我对这个结果很困惑。根据上述假设。有一个前面的初始化,并且遵守rf项目符号,因为它是一个常量表达式,即使不满足项目符号。(2.11.1)data(2.11.2)

所以,我想知道这句话到底是什么preceding initialization意思?如果这意味着变量的声明具有初始值设定项,那么func(0)第一个示例中的表达式怎么可能是常量表达式?

mpa*_*ark 6

结果似乎证明“前面的初始化”意味着“被初始化”,而不是有一个初始化器,因为第一个示例中的参数声明没有初始化器。

它确实意味着“被初始化”,但更重要的是关于正在评估的表达式上下文中先前初始化的可见性。在您的示例中,在评估编译器的上下文中,可以查看with的初始化。但是,在仅评估中的表达式的情况下,它看不到 的初始化。分析是本地的,因为它不会分析每个调用站点。这导致表达式本身不是常量表达式,而是常量表达式。func(0)rf0rffuncrfrffunc func(0)

如果你要这样写:

constexpr int func(int const& rf) {
  /* constexpr */ int const& v = rf;
  return v;
}

int main() {
  static int const data = 0;
  constexpr int value = func(data);
}
Run Code Online (Sandbox Code Playgroud)

这又没问题,因为在 的上下文中func(data)rf具有一个带有常量表达式的前置初始化data,并且具有v一个前置初始化,rf该初始化不是常量表达式,但其生命周期是在 的求值内开始的。func(data)