Padrões e Tipificação em C++: de Genéricos a Conceitos

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Genéricos e tipificação em C++: por que isso não é "apenas templates"?



Quando um desenvolvedor migra do Python ou Java para C++, muitas vezes a palavra "template" o assusta. Na mente surgem associações com colchetes angulares infinitos, erros de compilação incompreensíveis e a magia de std::vector<int>. Na verdade, genéricos em C++ (ou programação genérica) são uma ferramenta poderosa que permite escrever código uma vez e usá-lo com qualquer tipo de dado. E sim, isso não é a mesma coisa que genéricos em Java ou C#.



Neste artigo, vamos explorar como funciona a tipificação em C++ através de templates, como os templates de classes diferem dos templates de funções e por que os conceitos foram adicionados no C++20. Haverá muitos exemplos — desde os simples até os que realmente serão úteis em produção. Vamos lá!



O que são genéricos (templates) em C++?



De forma simples: templates em C++ são uma maneira de escrever código que funciona com qualquer tipo de dado, sem perder desempenho. Ao contrário da tipificação dinâmica do Python, onde o tipo é verificado em tempo de execução, o C++ gera uma versão separada da função ou classe para cada tipo usado em tempo de compilação. Isso é chamado de tipificação estática com parametrização.



Sintaticamente, um template é declarado usando a palavra-chave template e colchetes angulares com parâmetros:



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


Aqui, typename T é o parâmetro do template. Você pode usar class em vez de typename — não há diferença. Quando você escreve max(3, 7), o compilador substitui automaticamente int por T e cria a função int max(int, int). Se escrever max(3.14, 2.71) — obtém a versão para double. Simples e eficiente.



Templates de funções: o primeiro passo para genéricos



Vamos começar com o básico — templates de funções em C++. Esta é a maneira ideal de evitar duplicação de código quando a lógica é a mesma, mas os tipos são diferentes.



Exemplo: uma função que imprime um elemento no console (útil para depuração):



#include <iostream>#include <string>

template <typename T>void print(const T& value) { std::cout << value << std::endl;}

int main() { print(42); // int print(3.1415); // double print("Hello"); // const char* print(std::string("Genéricos!")); // std::string return 0;}


Observe: usamos const T& — isso é tipificação em C++ com passagem por referência constante, para evitar cópia de objetos grandes. Para tipos primitivos (int, double) isso não é crítico, mas é um bom hábito.



E se precisarmos passar dois argumentos de tipos diferentes? Fácil:



template <typename T1, typename T2>auto add(T1 a, T2 b) -> decltype(a + b) {    return a + b;}

// Em C++14 e posteriores, pode-se simplesmente:template <typename T1, typename T2>auto add(T1 a, T2 b) { return a + b;}


Aqui, auto deduz o tipo de retorno automaticamente. Isso é genéricos em ação — um código, infinitas combinações de tipos.



Templates de classes: construindo estruturas universais



Agora vamos para os templates de classes em C++. Esta é a base da biblioteca padrão (STL): std::vector<T>, std::map<Key, Value>, std::optional<T> — todos são implementados via templates.



Vamos escrever um exemplo simples, mas ilustrativo — uma classe template "Par" (análoga a std::pair):



template <typename First, typename Second>class Pair {private:    First first_;    Second second_;public:                

Blogs

Book Recommendations