C++: Fundamentos de Templates

Última atualização: 2026-08-26

Nas lições anteriores, as funções e classes que escrevemos só podiam lidar com um tipo.

Mas e se você quiser escrever uma função max que funcione com int, double e string?

Templates resolvem esse problema — permitindo que funções e classes suportem qualquer tipo.


1. O que são Templates?

(1) 1.1 Templates na Vida Real*

Analogia da Vida Real Equivalente na Programação
Uma forma de bolo (pode despejar diferentes massas) Template
Mala direta do Word (um template, preencher diferentes destinatários) Template

A essência dos templates: Deixar o compilador gerar automaticamente a versão apropriada de uma função ou classe com base nos tipos usados.

(2) 1.2 Por que Precisamos de Templates?

Sem templates (código repetido):

TEXT 📖 Somente leitura
#include <iostream>

// max for int
int max(int a, int b) {
 return a > b ? a : b;
}

// max for double
double max(double a, double b) {
 return a > b ? a : b;
}
// ... You'd have to write N versions!

Com templates (reutilização de código):

CPP
#include <iostream>

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

int main() {
 std::cout << max(3, 5) << std::endl; // Compiler auto-generates int version
 std::cout << max(3.14, 2.72) << std::endl; // Compiler auto-generates double version
 return 0;
}


2. Templates de Função*

(1) 2.1 Sintaxe Básica*

TEXT 📖 Somente leitura
template <typename TypeName>
ReturnType functionName(parameterList) {
 // function body
}

💡 Ponto-chave: typename também pode ser escrito como class (são equivalentes), mas typename é recomendado (mais intuitivo).

▶ Exemplo 1: Template de Função (Dificuldade ⭐)

CPP
#include <iostream>

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

int main() {
 std::cout << "max(3, 5) = " << max(3, 5) << std::endl;
 std::cout << "max(3.14, 2.72) = " << max(3.14, 2.72) << std::endl;
 
 // You can also explicitly specify the type
 std::cout << "max<int>(3, 5) = " << max<int>(3, 5) << std::endl;
 
 return 0;
}
▶ Experimente

Saída:

TEXT 📖 Somente leitura
max(3, 5) = 5
max(3.14, 2.72) = 3.14
max<int>(3, 5) = 5


3. Templates de Classe*

(1) 3.1 Sintaxe Básica*

TEXT 📖 Somente leitura
template <typename TypeName>
class ClassName {
 // members
};

▶ Exemplo 2: Template de Classe Pair (Dificuldade ⭐⭐)

CPP
#include <iostream>
#include <string>

// Class template: store a pair of values
template <typename T1, typename T2>
class Pair {
private:
 T1 first;
 T2 second;
 
public:
 Pair(const T1& a, const T2& b) : first(a), second(b) {}
 
 void print() {
 std::cout << "(" << first << ", " << second << ")" << std::endl;
 }
};

int main() {
 Pair<int, double> p1(3, 3.14);
 Pair<std::string, int> p2("Alice", 20);
 
 p1.print(); // (3, 3.14)
 p2.print(); // (Alice, 20)
 
 return 0;
}
▶ Experimente

Saída:

TEXT 📖 Somente leitura
(3, 3.14)
(Alice, 20)

💡 Ponto-chave: Templates de classe devem ter seus tipos explicitamente especificados quando usados (a menos que o construtor possa deduzi-los).



4. Declaração e Definição de Template*

(1) 4.1 O Problema: Onde Colocar os Templates?*

Se você colocar a declaração do template em .h e a definição em .cpp, obterá um erro de linker!

Razão: Um template não é uma função/classe real — é uma "forma" que gera código em tempo de compilação.

(2) 4.2 Solução: Colocar Declaração e Definição Juntas*

Abordagem recomendada: Coloque tanto a declaração quanto a definição do template no arquivo .h.

TEXT 📖 Somente leitura
// pair.h (header file)
#ifndef PAIR_H
#define PAIR_H

template <typename T1, typename T2>
class Pair {
private:
 T1 first;
 T2 second;
 
public:
 Pair(const T1& a, const T2& b);
 void print();
};

// Definition goes here too!
template <typename T1, typename T2>
Pair<T1, T2>::Pair(const T1& a, const T2& b) : first(a), second(b) {}

template <typename T1, typename T2>
void Pair<T1, T2>::print() {
 std::cout << "(" << first << ", " << second << ")" << std::endl;
}

#endif

💡 Dica: Essa é a maior diferença entre templates e funções/classes comuns — templates tipicamente têm declaração e definição juntas.



5. Prática: Template de Array Simples*

▶ Exemplo 3: Implementando o Template de Classe Array (Dificuldade ⭐⭐⭐)

CPP
#include <iostream>
#include <cassert>

template <typename T>
class Array {
private:
 T* data;
 int size;
 
public:
 Array(int sz) : size(sz) {
 data = new T[size];
 }
 
 ~Array() {
 delete data;
 }
 
 // Copy constructor (deep copy)
 Array(const Array& other) : size(other.size) {
 data = new T[size];
 for (int i = 0; i < size; i++) {
 data[i] = other.data[i];
 }
 }
 
 // Overload operator
 T& operator(int index) {
 assert(index >= 0 && index < size);
 return data[index];
 }
 
 int getSize() const {
 return size;
 }
};

int main() {
 Array<int> arr(5);
 for (int i = 0; i < arr.getSize(); i++) {
 arr[i] = (i + 1) * 10;
 }
 
 for (int i = 0; i < arr.getSize(); i++) {
 std::cout << arr[i] << " ";
 }
 std::cout << std::endl;
 
 return 0;
}
▶ Experimente

Saída:

TEXT 📖 Somente leitura
10 20 30 40 50 

▶ Exemplo 3: Template de Função (Dificuldade ⭐)

CPP
#include <iostream>

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

int main() {
    std::cout << "int max: " << getMax(3, 5) << std::endl;
    std::cout << "double max: " << getMax(3.14, 2.71) << std::endl;
    std::cout << "string max: " << getMax("apple", "banana") << std::endl;

    return 0;
}
▶ Experimente

Saída:

TEXT 📖 Somente leitura
int max: 5
double max: 3.14
string max: banana
💡 Dica: Templates permitem que funções funcionem com múltiplos tipos; o compilador automaticamente deduz o tipo real de T.


P: Qual a diferença entre templates e sobrecarga de funções? R:> - Sobrecarga de funções: múltiplas funções com o mesmo nome mas tipos de parâmetros diferentes (o compilador determina qual chamar em tempo de compilação) > - Templates de função: uma "forma" a partir da qual o compilador gera automaticamente a versão apropriada com base nos tipos usados > > Recomendação: Se a lógica é exatamente a mesma (apenas o tipo difere), use templates; se a lógica difere, use sobrecarga. P: Templates podem suportar todos os tipos? R: Não! Templates exigem que os tipos suportem certas operações. > > template <typename T> > T add(T a, T b) { > return a + b; // Requires T to support operator+ > } > > // If T is a custom class without an overloaded operator+, it will cause a compilation error. > P: Quando devo usar templates? R: Quando a lógica da sua função/classe é independente de tipo. > > Cenários típicos: > - Classes contêiner (std::vector, std::array) > - Algoritmos (std::sort, std::find) > - Funções utilitárias (std::max, std::min, std::swap)


P: Qual é a coisa mais importante sobre fundamentos de templates? R: Entenda os conceitos centrais primeiro, depois reforce-os através de exemplos práticos.


❓ Perguntas Frequentes

P: Declarações e definições de templates devem estar em arquivos de cabeçalho? R: Sim, templates exigem definições completas em tempo de compilação. Eles tipicamente são colocados em arquivos .h, ou você pode usar a palavra-chave export (C++20). P: Qual a diferença entre templates de classe e templates de função? R: Templates de função podem deduzir automaticamente os parâmetros de tipo, enquanto templates de classe exigem especificação explícita dos parâmetros de tipo.


📖 Resumo


📝 Exercícios

  1. Básico (Dificuldade ⭐): Escreva um template de função T min(T a, T b) que retorne o menor de dois valores.

  2. Intermediário (Dificuldade ⭐⭐): Escreva um template de classe BoxT com um membro do tipo T, e funções membro void set(T val) e T get().

  3. Desafio (Dificuldade ⭐⭐⭐): Estenda o template de classe Array acima adicionando:

  4. void push_back(const T& val) (expansão dinâmica)

  5. void pop_back()

  6. Implemente com templates para que possa armazenar qualquer tipo

6. 🚀 Próximos Passos*

Agora que você aprendeu os fundamentos de templates, a seguir vamos estudar Contêineres STL (lição 34) — usando os contêineres prontos fornecidos pela biblioteca padrão do C++, para que você não precise reinventar a roda!

Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%