gcc 和 clang 在表达式是否为常量的问题上存在分歧

cig*_*ien 13 c++ language-lawyer constant-expression c++20

对于以下程序:

struct S { int i; };

constexpr S f() { 
  return std::is_constant_evaluated() ? S{1} : S{0}; 
}

int main() {
  S s = f();
  return s.i;
}
Run Code Online (Sandbox Code Playgroud)

gcc 返回 0,clang 返回 1。 demo

我不认为 的评估f是在需要不断评估的上下文中进行的,所以我认为 clang 在这里是错误的。还是反过来?还是两个结果都有效?

Bar*_*rry 13

我们正在寻找的要求是表达式是否明显常量评估的,它在[expr.const]/14 中定义,即:

  • 一种 常量表达式,或
  • constexpr if 语句 ([stmt.if]) 的条件,或
  • 立即调用,或
  • 替换到原子约束表达式以确定是否满足的结果 ([temp.constr.atomic]),或
  • 可用于常量表达式或具有常量初始化的变量的初始值设定项。

这些条件中的前四个显然不成立。

对于最后一个,我们的变量不能用于常量表达式,因为它既不是 constexpr 也没有 const 限定的整数/枚举类型。这就是第五个条件的前半部分。

对于上一个的最后一部分,我们需要确定我们是否有常量初始化(不要与常量初始化混淆)。该定义在[basic.start.static]/2 中,强调我的:

恒定初始化如果一个变量或临时对象执行与静态或线程存储时限是恒定的初始化([expr.const])。

但是,s不是静态或线程存储持续时间的变量,所以没有固定的初始化,所以最后一个条件的最后一部分不抱任何。

因此,没有任何条件成立,并且在 OP 中,std::is_constant_evaluated() 应该返回false,这是一个叮当声错误。