Card 1 / 7
A concept is a named predicate on types, evaluated entirely at compile time. The most common way to write one is a requires-expression: it names some parameters of the type being tested and lists expressions that merely have to be valid. Nothing is executed, and no result is compared.
T |
Addable<T> |
|---|---|
int |
true |
double |
true |
std::string |
true — operator+ concatenates |
NoPlus (a struct with one int member) |
false |
The shape is requires(T left, T right) { left + right; }. The parenthesised list declares placeholder parameters that exist only inside the expression; the braced body holds the requirements, each ending in a semicolon.
left + right; is a simple requirement: it asks only "does this expression compile?". It never adds the two values, so a type whose operator+ does something absurd still satisfies the concept.
// A concept is a named, compile-time predicate on types. Write the right-hand
// side of this one as a REQUIRES-EXPRESSION: it introduces named parameters
// of the types being tested, then lists expressions that must simply be
// VALID. Nothing is evaluated and no result is compared.
//
// requires(T left, T right) { left + right; }
//
// Fill in the right-hand side so Addable<T> is satisfied exactly when two T
// values can be added.
template <class T>
concept Addable =
requires(T left, T right) { left + right; }
;Card 2 / 7
A requires-expression can demand more than valid expressions. A type requirement — the word typename followed by a type name — is satisfied when that type exists, which is the concepts replacement for a whole void_t detection trait.