Pular para conteúdo

Templates e Conceitos

Templates definem famílias de tipos ou funções. A instanciação substitui argumentos e verifica o programa. Conceitos nomeiam restrições e melhoram interfaces e diagnósticos.

Template de função

template<typename T>
T maximum(T left, T right) {
    return left < right ? right : left;
}

Isso exige < utilizável e retorno compatível, mas a assinatura não comunica a exigência.

Template restrito

#include <concepts>

template<std::totally_ordered T>
T maximum(T left, T right) {
    return left < right ? right : left;
}

Conceito é predicado em compilação. Especifica sintaxe e, por documentação, expectativas comportamentais. O compilador não prova leis como transitividade.

Conceito personalizado

template<typename R>
concept SizedRange = requires(R const& range) {
    { range.size() } -> std::convertible_to<std::size_t>;
    range.begin();
    range.end();
};

Restrinja no nível realmente necessário; exigir contêiner concreto reduz reutilização.

Instanciação e visibilidade

Definições precisam estar visíveis na instanciação implícita, por isso ficam em headers. Instanciação explícita pode mover gerações selecionadas. Toda especialização obedece à ODR.

Templates de classe e dedução

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

private:
    T value_;
};

box value{std::string{"notes"}}; // class template argument deduction

Polimorfismo estático e type erasure

Templates permitem inlining concreto. Type erasure, como std::function, oferece interface uniforme em runtime. Interfaces virtuais, variants, templates e apagamento diferem em extensibilidade, alocação, ABI, compilação e diagnósticos.

Exercícios

  1. Restrinja função de média a intervalo numérico e resultado válido.
  2. Explique propriedades semânticas que um conceito não prova.
  3. Compare estratégia virtual e por template.