C/C++ Arena

Step 4 of 7

Concepts

A plain template accepts any type. If the type doesn't fit, the error appears deep inside the template's body, often as a wall of messages about code you didn't write. Concepts (C++20) state the requirements up front, in the signature, so misuse is rejected immediately with a short, clear error.

#include <concepts>
#include <iostream>
#include <string>
#include <vector>

template <std::integral T>
bool is_even(T n) { return n % 2 == 0; }

template <typename T>
concept Sized = requires(const T& t) {
    { t.size() } -> std::convertible_to<std::size_t>;
};

template <Sized C>
bool is_empty(const C& c) { return c.size() == 0; }

int main() {
    std::cout << is_even(10) << is_even(7L) << "\n";
    std::cout << is_empty(std::string("")) << is_empty(std::vector<int>{1}) << "\n";
    // is_even(2.5);   // error: 'double' does not satisfy 'integral'
    // is_empty(42);   // error: 'int' does not satisfy 'Sized'
}
10
10

How it works

Your task: Euclid's algorithm

The greatest common divisor of a and b equals the gcd of b and a % b, and gcd(a, 0) is a. So loop while b != 0:

(48, 18) -> (18, 12) -> (12, 6) -> (6, 0)   answer 6

Use a temporary to do the swap: T t = a % b; a = b; b = t;. The std::integral constraint is required: % doesn't work on doubles, and the tests check that a double call is rejected.

Your turn: write template <std::integral T> T gcd(T a, T b) using Euclid's algorithm: while b != 0, replace (a, b) with (b, a % b). The tests also check that calling it with a double is rejected.

Previous: std::string_view Next: Ranges