具有非平凡constexpr析构函数的consteval函数返回对象

时间:2019-10-14 18:01:28

标签: c++ language-lawyer c++20

C ++ 20将使用新的consteval关键字,如果一切顺利,将使用constexpr destructor。 遗憾的是,目前我所知没有编译器实现consteval。 以下代码是否有效?

struct A {
  constexpr ~A() {}
};

consteval A f() {
    return A{};
}

void test() {
    A a;
    a = f(); // <-- here
}

问题出在我标记的行上-需要调用A返回的临时f的析构函数。但应在完整表达式的结尾处调用它。因此不在即时评估之内。

我在constevalconstexpr destructor的论文中都没有找到明确禁止这样做的引文,但我看不出它怎么正确。

以下代码在C ++ 20中是否有效? 此代码应如何处理?


注意:

consteval paper中,给出了此示例。这里的consteval函数在常量上下文之外被调用。

consteval int sqr(int n) {
  return n*n;
}
constexpr int r = sqr(100);  // Okay.
int x = 100;
int r2 = sqr(x);  // Error: Call does not produce a constant.

1 个答案:

答案 0 :(得分:3)

我认为这段代码很好。

consteval的显着方面是[expr.const]/12

  

表达式或转换位于立即函数上下文中,前提是该表达式或转换可能被求值,并且其最里面的非块范围是立即函数的函数参数范围。如果表达式或转换是立即函数的显式或隐式调用,并且不在立即函数上下文中,则它是立即调用。立即调用应为常量表达式。

void test() {
    A a;
    a = f(); // <-- here
}

f()立即调用(它是对不在立即函数上下文中的立即函数的显式调用)。因此,要求f()必须是一个常量表达式。

请注意:仅f(),而不是a = f();,此处的赋值运算符不必为常量表达式。

f()调用的所有内容都很好。 A的所有特殊成员函数在恒定的评估时间内均可调用。 f()的结果是常量表达式([expr.const]/10)的允许结果,同样地,因为它也不会触发任何限制(A没有指针或引用成员,因此很简单)它们都没有引用没有静态存储持续时间的对象。

最终,持续评估的问题归结为要遍历所有限制条件并查看是否有任何中断。我认为我们没有违反任何规则,所以应该没事。