Document #: | P3822R0 [Latest] [Status] |
Date: | 2025-09-01 |
Project: | Programming Language C++ |
Audience: |
EWGi |
Reply-to: |
Viacheslav Luchkin <someone12469@gmail.com> Gašper Ažman <gasper.azman@gmail.com> |
This paper extends compound requirements to allow noexcept specifiers
to be applied conditionally. The proposed syntax for this is requires { { expression } noexcept(condition) -> return-type-constraint; }
.
Requires-expressions can be used to assert that an expression is non-throwing, but do not provide a way to do so conditionally, which is sometimes needed in generic programming. Achieving this now usually requires code duplication.
The lack of support for this syntax is also inconsistent with function declarations, which have had conditional noexcept specifiers since C++11.
Motivational example:
Before
|
After
|
---|---|
|
|
Redefine the syntax for compound requirements as follows:
compound-requirement:
{
expression}
noexcept-specifieropt return-type-requirementoptnoexcept
opt;
noexcept-specifier:
noexcept(
condition)
noexcept
return-type-requirement:
->
type-constraint
Where the condition, if supplied, shall be a contextually
converted constant expression of type
bool
. The
noexcept-specifier
noexcept
without a condition is equivalent to noexcept(true)
.
If condition evaluates to
true
and
expression is a potentially-throwing expression, the
requirement is not satisfied. If condition evaluates to
false
or the
noexcept-specifier is absent, expression may be
potentially-throwing.
If the conversion of condition to
bool
fails,
the requirement is not satisfied. This is not a hard error, because
requirements are often used in overload resolution and the expected
behavior for an unexpected input type is that other overloads are still
considered.
Recall that the grammar for noexcept-specifier is defined in section 14.5 [except.spec] as follows:
noexcept-specifier:
noexcept(
constant-expression)
noexcept
Alter section 7.5.8.4 [expr.prim.req.compound] as follows:
compound-requirement:
{
expression}
noexcept-specifieropt return-type-requirementoptnoexcept
opt;
return-type-requirement:
->
type-constraint1 A compound-requirement asserts properties of the expression E. The expression is an unevaluated operand. Substitution of template arguments (if any) and verification of semantic properties proceed in the following order:
- (1.1) Substitution of template arguments (if any) into the expression is performed.
- (1.2) If the
noexcept
specifier is present, E shall not be a potentially-throwing expression ([except.spec])
- (1.2) If the noexcept-specifier ([except.spec]) is present, then:
- (1.2.1) Substitution of template arguments (if any) into its associated constant-expression is performed. The noexcept-specifier
noexcept
without a constant-expression is equivalent tonoexcept(true)
.- (1.2.2) The constant-expression shall be a contextually converted constant expression of type
bool
([expr.const]). If the constant-expression is true, E shall not be a potentially-throwing expression ([except.spec]).
Bump feature-test macro
__cpp_concepts
in section
15.12
[cpp.predefined]:
__cpp_char8_t 202207L- __cpp_concepts 202002L
+ __cpp_concepts 20XXXXL
__cpp_conditional_explicit 201806L