# Concepts and Constraints (C++20) — C++

Source: https://www.skillbyai.com/en/cpp/t-concepts

> Constrain templates with concepts for clearer interfaces and errors.

## Saying what a type must support

Before C++20, template requirements were implicit: if you called `sort` on something without `operator<`, you got pages of errors from deep inside the library. **Concepts** make requirements **explicit**. A concept is a named compile-time predicate on types, such as the standard `std::integral`, `std::floating_point`, `std::totally_ordered`, `std::copyable`, `std::invocable` and `std::ranges::range`. Use them to **constrain** templates: `template <std::integral T> T gcd(T a, T b)`, or with the abbreviated syntax `auto gcd(std::integral auto a, std::integral auto b)`. Write your own with **`requires` expressions** that list valid operations: `concept Shape = requires(const T& s) { { s.area() } -> std::convertible_to<double>; };`. Calls with unsuitable types now fail **at the call site** with a short message naming the unmet concept. Concepts also enable **overloading on constraints**: the compiler picks the most constrained matching overload. Earlier techniques such as SFINAE and `std::enable_if` achieved similar effects with much more obscure code.

## Standard and custom concepts

A call with the wrong type fails with a clear concept error.

```cpp
#include <concepts>
#include <numbers>
#include <vector>

template <std::integral T>
T gcd(T a, T b) {
    while (b != 0) { T t = a % b; a = b; b = t; }
    return a;
}

template <typename T>
concept Shape = requires(const T& s) {
    { s.area() } -> std::convertible_to<double>;
};

struct Circle { double r; double area() const { return std::numbers::pi * r * r; } };
struct Rect   { double w, h; double area() const { return w * h; } };

double total_area(const std::vector<Circle>& cs) {
    double t = 0; for (const auto& c : cs) t += c.area(); return t;
}

double area_of(const Shape auto& s) { return s.area(); }   // abbreviated template syntax

int main() {
    auto g = gcd(84, 36);            // 12
    // gcd(3.5, 1.5);                // error: double does not satisfy std::integral
    double a = area_of(Rect{3, 4});
    // area_of(42);                  // error: int does not satisfy Shape
}
```

## Job requirements on a posting

Before concepts, a template was a job posting with no requirements listed: unsuitable applicants were rejected only after a long, confusing interview. Concepts print the requirements on the posting, so mismatches are caught at the door.

**Quiz:** What is the main benefit of C++20 concepts?

- [ ] They make programs run faster
- [x] They state template requirements explicitly, giving clearer interfaces and error messages
- [ ] They replace classes
- [ ] They enable garbage collection

*Answer:* They state template requirements explicitly, giving clearer interfaces and error messages. Concepts document and check requirements on template arguments at the call site.
