Historically, C++ templates were completely unconstrained. If you wrote a function that added two variables using the + operator and a developer passed a type that did not support addition, the compiler would attempt to build the function body anyway, resulting in massive compiler errors that were incredibly difficult to parse.
C++20 solved this problem by introducing Concepts, allowing you to explicitly constrain template parameters.
The Nightmare of Unconstrained Errors
If a template compilation fails deep inside a nested function, the compiler prints every single attempted template substitution path. This creates a wall of error text. Concepts fix this by validating types before compiling the function body.
C++20 Concepts and the `requires` Clause
Concepts define constraints that types must satisfy. The standard library provides built in concepts like std::integral, std::floating_point, and std::copyable:
Creating Custom Concepts
You can define your own concepts using the concept keyword and requires expressions to check for method signatures or operators:
* The Security Guard Metaphor: Think of C++20 Concepts like hiring a security guard at the door of your function. In old C++ templates, anyone could enter. The compiler only noticed they did not fit when they started breaking chairs inside (attempting to use operators they did not support), forcing a chaotic cleanup. Concepts stop visitors at the door, check their type credentials, and reject them instantly if they do not match, producing a clean error message.