June's C++23 plenary adds if consteval for constant-evaluation dispatch
if consteval separates constant-evaluation paths without the trap of testing is_constant_evaluated inside if constexpr. The June plenary also adopts targeted library integration changes.
if constexpr (std::is_constant_evaluated()) looks like a natural way to select code for constant evaluation. It instead asks the question in a context that already requires constant evaluation, making the condition true. A programmer can select the constant path permanently while believing the function still has a runtime alternative.
The June virtual plenary adopts if consteval to address that trap and a related problem with immediate functions. Herb Sutter's June 9 report describes the June 7 meeting as the third full-committee plenary of the pandemic. It records another set of targeted additions to the C++23 working draft. The date here follows the published report so that its account is available to cite.
I find this a worthwhile change because it removes a plausible misuse of two individually useful features. C++'s several forms of compile-time programming need rules that compose. A familiar-looking combination that silently asks the wrong question adds a maintenance cost beyond the feature's syntax.
A language form establishes the context
P1938R3, by Barry Revzin, Richard Smith, Andrew Sutton, and Daveed Vandevoorde, describes both motivating problems. The first is the misleading if constexpr use. The second is that a normal if using is_constant_evaluated does not establish the immediate-function context needed for some calls to consteval functions.
A consteval function must be used under the language's immediate-invocation rules. Calling it with a parameter of an enclosing constexpr function can be ill-formed even inside a normal conditional that will only execute during constant evaluation. The conditional's runtime behavior does not by itself relax the rules applying to that call.
if consteval establishes the necessary context in its constant-evaluation branch. It has no parenthesized condition. During constant evaluation, the first branch runs. Otherwise the optional else branch runs. The syntax directly names the selection being made instead of embedding a library query in another compile-time selection construct.
An illustrative use of the adopted draft facility is:
consteval int immediate_increment(int value)
{
return value + 1;
}
constexpr int increment(int value)
{
if consteval {
return immediate_increment(value);
} else {
return value + 1;
}
}
The example demonstrates context selection, not a new overflow policy for integer addition. Both branches still have their own ordinary correctness requirements. A library might use a portable loop during constant evaluation and a specialized runtime implementation in the other branch, but the language feature does not independently prove that their results agree.
Braces distinguish the changed rules
The proposal requires compound statements for the branches. Its rationale uses braces to make the changed evaluation context visible and avoid suggesting that an arbitrary boolean condition can be combined with consteval. The paper discusses why a spelling such as if (consteval && condition) would introduce a harder problem of proving when an immediate call is permitted.
There is also a negated form, if !consteval, with the corresponding branch selection reversed. A caller need not invent another boolean utility for the inverse case. The design still leaves std::is_constant_evaluated available because the function form has uses involving additional conditions and recognizable diagnostics.
P1938 proposes a dedicated feature-test macro, __cpp_if_consteval, to identify support. This is a language addition, so the syntax itself requires a compiler that recognizes it. A fallback using an ordinary library query cannot always reproduce its immediate-function-context behavior, even if it appears to choose the same branch. Compatibility code must account for the operation needed inside that branch as well as the condition being tested.
This distinction helps explain why the addition is more than a shorter spelling. A normal if query and if consteval can select the same execution path, yet the new language form also changes the context governing immediate calls. That semantic difference is what allows the two constant-evaluation facilities to compose in the paper's example.
I prefer that rule to requiring every reader to remember why a seemingly protective conditional is insufficient. The compiler can recognize the branch's context directly. The resulting source describes the intended distinction between constant evaluation and ordinary execution at the point where the implementations diverge.
The meeting also addresses interface boundaries
Sutter's report records adoption of out_ptr and inout_ptr for adapting smart pointers to APIs with pointer-to-pointer output parameters. Their helper objects update the wrapped smart pointer when the helper is destroyed. That is another integration change, connecting C++ ownership objects to interfaces commonly expressed in C terms.
The report also distinguishes the Concurrency TS work from additions to the C++23 draft. Hazard-pointer and read-copy-update work proceeds into that separate technical specification. Approval for a TS does not establish that its facilities have entered the main language standard.
These distinctions give the June decisions their practical meaning. if consteval enters the working draft with a defined context rule, while other accepted work targets a different document. Neither status alone establishes availability in an installed compiler or library. Implementations can adopt draft features independently, so source using the new branch form needs compiler support for that specific language facility.