C ++ 20将使用新的consteval关键字,如果一切顺利,将使用constexpr destructor。 遗憾的是,目前我所知没有编译器实现consteval。 以下代码是否有效?
struct A {
constexpr ~A() {}
};
consteval A f() {
return A{};
}
void test() {
A a;
a = f(); // <-- here
}
问题出在我标记的行上-需要调用A
返回的临时f
的析构函数。但应在完整表达式的结尾处调用它。因此不在即时评估之内。
我在consteval和constexpr 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.
答案 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
没有指针或引用成员,因此很简单)它们都没有引用没有静态存储持续时间的对象。
最终,持续评估的问题归结为要遍历所有限制条件并查看是否有任何中断。我认为我们没有违反任何规则,所以应该没事。