Skip to main content
The requires keyword in C++20 introduces compile-time constraints on template parameters, restricting the set of types or values that can be substituted during template instantiation. It operates by evaluating boolean constant expressions or checking the well-formedness of expressions and types. If a constraint is not satisfied, the template is discarded from the overload resolution set. Crucially, constraint checking is a distinct phase that occurs after template argument substitution has successfully completed. Therefore, discarding a candidate due to an unsatisfied requires clause is a constraint failure, not a SFINAE (Substitution Failure Is Not An Error) failure. In C++, requires manifests in two distinct but interacting grammatical constructs: the requires clause and the requires expression.

The Requires Clause

A requires clause is appended to a template declaration or a function declaration to specify the actual constraints. It must evaluate to a boolean constant expression (true or false). A requires clause can be positioned in two places:
  1. Immediately following the template parameter list.
  2. As a trailing requires clause, following the function declarator.

The Requires Expression

A requires expression is a boolean prvalue expression of type bool that evaluates whether a specific set of syntactic requirements are well-formed. It does not execute code; it operates entirely in an unevaluated context (similar to decltype or sizeof).
The parameter-list declares local variables that are used exclusively within the requirement-sequence to test operations.

Types of Requirements

Inside the body of a requires expression, you can define four distinct types of requirements:

1. Simple Requirements

A simple requirement is an arbitrary expression statement. The compiler checks only if the expression is well-formed (i.e., it compiles). It does not evaluate the result or check the return type.

2. Type Requirements

Introduced by the typename keyword, a type requirement asserts that a specific nested type, type alias, or class template specialization is valid and exists. It only checks if the type can be formed.

3. Compound Requirements

A compound requirement is enclosed in braces {} and allows you to constrain the return type of an expression and/or assert that the expression does not throw exceptions (noexcept).

4. Nested Requirements

A nested requirement is introduced by an additional requires keyword followed by a boolean constant expression. Unlike simple requirements that check if an expression is well-formed, a nested requirement checks if an expression evaluates to true.

The requires requires Idiom

Because a requires clause expects a boolean expression, and a requires expression yields a boolean, they are frequently combined to create ad-hoc constraints directly on a template without defining a standalone Concept. The first requires initiates the clause, and the second requires initiates the expression.
In this construct, the template transmit is only viable if T possesses a serialize() method and a nested iterator type.
Tired of Poor C++ Skills? Fix That With Deep Grasping!Learn More