पाठ 17 / 25

Concepts and Constraints (C++20)

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.

#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.

त्वरित जाँच: What is the main benefit of C++20 concepts?

  • They make programs run faster
  • 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.