C++ · 4 · Templates & Generic Programming19 / 36 · 53%
Concepts (C++20)
Constrain templates so errors point at the call site, not 400 lines into the library.
Examples: concept, requires, std::integral
shortcuts: ← prev · → next · M mark
1
Using a Concept
Say what the type must support.
Example
example
#include <concepts>
template <std::integral T>
T gcd(T a, T b) { while (b) { T t = b; b = a % b; a = t; } return a; }
gcd(12, 18); // ok
// gcd(1.5, 2.0); // error: does not satisfy std::integral2
Defining One
A concept is a compile-time predicate on types.
Example
example
template <typename T>
concept Drawable = requires(const T& t, Canvas& c) {
{ t.draw(c) } -> std::same_as<void>;
{ t.bounds() } -> std::convertible_to<Rect>;
};
template <Drawable T> void render(const T& shape);3
requires Clauses
Combine constraints with && and ||.
Example
example
template <typename T>
requires std::copyable<T> && (sizeof(T) <= 64)
void store(T value);
void f(const auto& x) requires Drawable<decltype(x)>;4
Before & After
The real benefit is the error message.
Unconstrained template
| symptom | detail |
|---|---|
| error site | deep inside library |
| length | hundreds of lines |
| cause | hidden |
Concept-constrained
| symptom | detail |
|---|---|
| error site | the call |
| length | a few lines |
| cause | named constraint |