requires
- C++ course
- Advanced
- Lesson 62/83
- 5 min
Learn template constraints with the requires clause.
What is a requires clause?
The requires keyword appears in two forms: the requires clause (a template constraint) and the requires expression (an expression check). A requires expression checks whether a set of expressions is valid and returns bool.
Example: requires(T a, T b) { a + b; a - b; }. This expression returns true when both a + b and a - b are valid. It can live inside a concept or be used as a template constraint. This way the operations a type supports are queried at compile time.
Using a requires clause
To constrain a template function, write requires after the template header: template<typename T> requires Hashable<T> size_t hash_of(T v).
Now hash_of can be called only with types that satisfy Hashable. If the condition fails, the compiler gives a short and clear error. The requires clause can also combine concept names with && and ||: requires Hashable<T> && std::copyable<T>.
Practice Define the Hashable concept
Define the Hashable concept using the body requires(T a) { { std::hash<T>{}(a) } -> std::convertible_to<size_t>; }. In main test it with static_assert(Hashable<int>); and print "Hashable test passed" with std::cout.
Starter code
#include <iostream>
#include <concepts>
#include <functional>
// Define the Hashable concept here
int main() {
// Test for int and print a message
return 0;
}Sample solution
#include <iostream>
#include <concepts>
#include <functional>
template<typename T>
concept Hashable = requires(T a) {
{ std::hash<T>{}(a) } -> std::convertible_to<size_t>;
};
int main() {
static_assert(Hashable<int>);
std::cout << "Hashable test passed";
return 0;
}Expected output
Hashable test passed
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 the requires expression
template<typename T> concept Hashable = ____(T a) { std::hash<T>{}(a); };
template<typename T> concept Hashable = requires(T a) { std::hash<T>{}(a); };
Explanation: A requires expression is written with a parameter list and a body.
2 What does requires(T a) { a.foo(); } check?
- That a is a class
- That a is not null
- That the call a.foo() is valid on type a Correct answer
- That a.foo() returns a method
Explanation: The requires expression checks whether the call a.foo() is valid at compile time.
3 Match each piece to its role
| Term | Meaning |
|---|---|
requires(T a, T b) |
Expression check |
requires Hashable<T> |
Template constraint |
a + b |
Tested expression |
std::hash<T>{}(a) |
Hash call |