C++20 will have the new consteval keyword and constexpr destructor if all goes well. Sadly no compiler that I know of implements consteval at this time. Will the following code be valid?
struct A {
constexpr ~A() {}
};
consteval A f() {
return A{};
}
void test() {
A a;
a = f(); // <-- here
}
The issue comes from the line I marked — the destructor of the temporary A
returned by f
need to be called. but it should be called at the end of the full expression. so outside of the immediate evaluation.
I didn't find any quotes from the consteval and constexpr destructor papers that explicitly forbid this, but I can't see how it could be correct.
Will the following code be valid in C++20? What should happen with this code?
Note:
In the consteval paper, this example is given. Here the consteval function is called outside of constant context.
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.
I think this code is fine.
The salient aspect of consteval
is [expr.const]/12:
An expression or conversion is in an immediate function context if it is potentially evaluated and its innermost non-block scope is a function parameter scope of an immediate function. An expression or conversion is an immediate invocation if it is an explicit or implicit invocation of an immediate function and is not in an immediate function context. An immediate invocation shall be a constant expression.
In
void test() {
A a;
a = f(); // <-- here
}
f()
is an immediate invocation (it is an explicit invocation of an immediate function that is not in an immediate function context). So the requirement is that f()
has to be a constant expression.
Note: just f()
, not a = f();
, there is no requirement that the assignment operator here is a constant expression.
Everything that f()
invokes is perfectly fine. All of A
's special member functions are invocable during constant evaluation time. The result of f()
is a permitted result of a constant expression ([expr.const]/10) likewise because it does not trigger any of the restrictions there either (A
has no pointer or reference members, so trivially none of them refer to objects without static storage duration).
Ultimately, the question of constant evaluation boils down to going through all the list of restrictions and seeing if anything breaks. I don't think we violate any of the rules, so this should be fine.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With