Generics em C++: para que servem e como usar para iniciantes

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

Generics em C++: para que servem e como usar

\n\n

Todo programador, mais cedo ou mais tarde, se depara com uma situação em que precisa escrever uma função que funcione com diferentes tipos de dados. Por exemplo, uma função para encontrar o elemento máximo — ela deve funcionar igualmente bem com int, double e string. Sem ferramentas especiais, seria necessário escrever uma implementação separada para cada tipo. É aqui que os generics (tipos genéricos) ou, como são chamados em C++, os templates, vêm em socorro.

\n\n

Em C++, o mecanismo de templates é a base da programação genérica. Ele permite escrever código que funciona com qualquer tipo de dados, sem sacrificar o desempenho. Neste artigo, vamos entender o que são generics em C++, para que servem e como usá-los na prática. O material é voltado para iniciantes, então vamos progredir do simples ao complexo.

\n\n

O que são templates (generics) em C++?

\n\n

Um template é uma construção que permite definir uma função ou classe que funciona com um tipo de dados arbitrário. Em vez de um tipo específico, você especifica um parâmetro de tipo (por exemplo, T), e o compilador, durante a compilação, substitui pelo tipo necessário. Isso é chamado de instanciação de template.

\n\n

Imagine uma forma de cortar biscoitos. A forma é uma só, mas os biscoitos podem ser feitos com diferentes massas: amanteigada, de chocolate, de aveia. O template é a forma, e o tipo (int, double, string) é a massa. Você descreve o algoritmo uma vez, e o compilador cria automaticamente versões para os tipos necessários.

\n\n

Existem dois tipos de templates:

\n
    \n
  • Templates de funções — para criar funções genéricas.
  • \n
  • Templates de classes — para criar classes genéricas (por exemplo, contêineres).
  • \n
\n\n

Templates de funções: o primeiro passo para o código genérico

\n\n

Vamos começar com o mais simples — uma função template. Suponha que precisamos de uma função que retorne o máximo de dois valores. Veja como ela seria sem templates:

\n\n
int max_int(int a, int b) {\n    return (a > b) ? a : b;\n}\n\ndouble max_double(double a, double b) {\n    return (a > b) ? a : b;\n}
\n\n

O código se repete. Com um template, isso é resolvido de forma elegante:

\n\n
#include <iostream>\n#include <string>\n\ntemplate <typename T>\nT max_value(T a, T b) {\n    return (a > b) ? a : b;\n}\n\nint main() {\n    std::cout << max_value(10, 20) << std::endl;           // 20\n    std::cout << max_value(3.14, 2.71) << std::endl;       // 3.14\n    std::cout << max_value(std::string("apple"), \n                             std::string("banana")) << std::endl; // banana\n    return 0;\n}
\n\n

A palavra-chave template informa ao compilador que isso é um template. <typename T> é a lista de parâmetros do template. T é um nome condicional para o tipo que será substituído posteriormente. Em vez de typename, pode-se usar class — não há diferença:

\n\n
template <class T>\nT max_value(T a, T b) {\n    return (a > b) ? a : b;\n}
\n\n

Quando você chama max_value(10, 20), o compilador vê que os argumentos são int e cria automaticamente uma versão da função para int. Esse processo é chamado de dedução de tipos. Se necessário, você pode especificar o tipo explicitamente:

\n\n
std::cout << max_value<double>(5, 7.5) << std::endl; // 7.5
\n\n

Importante: a função template deve ser definida em um arquivo de cabeçalho (ou antes de seu uso), pois o compilador precisa ver a definição completa para a instanciação.

\n\n

Templates de classes: criando contêineres universais

\n\n

Templates de classes são uma ferramenta ainda mais poderosa. O exemplo mais marcante são os contêineres da biblioteca padrão (STL): std::vector<int>, st

Blogs

Book Recommendations