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.
Abstract Syntax Tree (AST) Simplification
With the old SFINAE hack, the compiler had to construct a massive Abstract Syntax Tree (AST) in memory for every possible template, try to substitute types, wait for it to fail, and then discard the AST. This caused compile times to explode.
Concepts let the compiler reject invalid template arguments earlier in overload resolution, often producing shorter diagnostics than deep instantiation failures. They do not skip parsing or AST construction entirely, rather, failed concept checks remove candidates before the compiler instantiates unusable bodies.
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.