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

标签 c++ language-lawyer c++20 constant-expression

对于以下程序:

struct S { int i; };

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

int main() {
  S s = f();
  return s.i;
}
gcc 返回 0,clang 返回 1。demo
我不认为f的评价是在需要不断评估的上下文中完成的,所以我认为 clang 在这里是错误的。还是反过来?还是两个结果都有效?

最佳答案

我们正在寻找的要求是表达式是否为 manifestly constant-evaluated ,定义于 [expr.const]/14 ,即:

  • a constant-expression, or
  • the condition of a constexpr if statement ([stmt.if]), or
  • an immediate invocation, or
  • the result of substitution into an atomic constraint expression to determine whether it is satisfied ([temp.constr.atomic]), or
  • the initializer of a variable that is usable in constant expressions or has constant initialization.

这些条件中的前四个显然不成立。
对于最后一个,我们的变量不能用于常量表达式,因为它既不是 constexpr 也没有 const 限定的整数/枚举类型。这就是第五个条件的前半部分。
对于上一个的最后一部分,我们需要确定我们是否有常量初始化(不要与常量初始化混淆)。该定义在 [basic.start.static]/2 ,强调我的:

Constant initialization is performed if a variable or temporary object with static or thread storage duration is constant-initialized ([expr.const]).


但是s不是具有静态或线程存储持续时间的变量,因此没有常量初始化,因此最后一个条件的最后部分也不成立。
因此,没有任何条件成立,并且在 OP 中,std::is_constant_evaluated()应该返回 false这是一个 clang 错误。

关于c++ - gcc 和 clang 在表达式是否为常量的问题上存在分歧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62822725/

相关文章:

c++ - 如此处所述,使用指向指针的指针可以解决类成员的非更新问题吗?如果是如何?

c++ - constexpr 和可变成员以及隐式复制构造函数

c++ - 您必须使用无限循环才能有效地重用协程句柄?

c++ - 使用 Qt 开发 C++ 程序

c++ - 从 DWORD 中提取 lo 和 hi 字时为什么需要二进制移位?

c++ - 尝试从另一个 .cpp 启动 TShape 时成员标识符预期错误

c++ - std::list 的多元素插入是强异常安全的吗?

c++ - 在 C++ 标准中,哪里声明了 const 右值引用不绑定(bind)到左值?

c++ - 否定和德摩根定律不是 C++20 部分按约束排序的一部分

c++ - 析构函数必须对默认初始化的类成员才可用(公共(public))还是完全有效?