Templates and Generics

Templates and Generics

Function templates, class templates, constraints, and generic programming patterns.

Templates and Generics

Function templates

template <typename T>
T max_of(T a, T b) {
    return a > b ? a : b;
}

Class templates

template <typename T>
class Box {
public:
    explicit Box(T value) : value_{std::move(value)} {}
    const T& get() const { return value_; }

private:
    T value_;
};

Non-type template parameters

template <typename T, std::size_t N>
class FixedBuffer {
    std::array<T, N> data_{};
};

Concepts and requires

template <typename T>
concept Addable = requires(T a, T b) {
    a + b;
};

template <Addable T>
T sum(T a, T b) {
    return a + b;
}

Useful standard traits

Best-practice reminders

Abbreviated templates and named constraints

std::integral auto clamp_positive(std::integral auto value) {
    return value < 0 ? 0 : value;
}

Abbreviated templates are convenient for small interfaces, but named template parameters are usually clearer for bigger APIs.

requires clauses and nested requirements

template <typename T>
concept Reservable = requires(T container, std::size_t n) {
    container.reserve(n);
    typename T::value_type;
};

template <typename T>
requires Reservable<T>
void prepare(T& container, std::size_t n) {
    container.reserve(n);
}

Useful modern traits and helpers

When if constexpr helps

Use if constexpr to keep one generic algorithm readable instead of splitting simple type-based branches into separate overloads.