Search⌘ K
AI Features

Composing Constraints

Explore how to compose multiple constraints in C++ templates using conjunctions and disjunctions. Understand short-circuit evaluation, atomic constraints, and techniques for constraining parameter packs to write safer and clearer template code.

We have seen multiple examples of constraining template arguments, but in all the cases so far, we used a single constraint. It’s possible, though, for constraints to be composed using the && and || operators. A composition of two constraints using the && operator is called a conjunction and the composition of two constraints using the || operator is called a disjunction.

Constraint conjunctions

For a conjunction to be true, both constraints must be true. Like in the case of logical AND operations, the two constraints are evaluated from left to right, and if the left constraint is false, the right constraint is not evaluated. Let’s look at an example:

template<typename T>
requires std::is_integral_v<T> && std::is_signed_v<T>
T decrement(T value)
{
return value--;
}
Performing constraint conjunction using requires expression

In this snippet, we have a function template that returns the decremented value of the received argument. However, it only accepts signed integral values. This is specified with the conjunction of two constraints, std::is_integral_v<T> && std::is_ signed_v<T>. The same result can be achieved using a different approach to defining the conjunction, as shown next:

template<typename T>
concept Integral = std::is_integral_v<T>;
template<typename T>
concept Signed = std::is_signed_v<T>;
template<typename T>
concept SignedIntegral = Integral<T> && Signed<T>;
template<SignedIngeral T>
T decrement(T value)
{
return value--;
}
Performing constraint conjunction using concepts

We can see three concepts defined here: one that constrains integral types, one that constrains signed types, and one that constrains ...