Template
- #c++
- #template
- #programmazione generica
- #oop
In questa lezione
- 1. Introduzione
- Perché usare i template?
- Come funziona la compilazione dei template
- 2. Template di Funzione
- Esempio base
- 3. Template di Classe
- 4. Template con più parametri
- 5. Parametri di default nei Template
- 6. Specializzazione dei Template
- 7. Template e Funzioni Membro
- 8. Template Avanzati
- 8.1 Template Template Parameters
- 8.2 Concepts (C++20)
- 9. Esempio pratico: Stack generico
- 10. Esercizi
- 10.1 Esercizio - Funzione Generica maxGenerico
- 10.2 Esercizio - Classe Template Coppia
- 10.3 Esercizio - Stack Generico
- 11. Quiz a risposta multipla
1. Introduzione
I template in C++ sono uno strumento fondamentale per scrivere codice generico, riutilizzabile e flessibile.
Permettono di definire funzioni e classi che operano su tipi diversi, senza dover riscrivere lo stesso codice per ogni tipo di dato.

Nota
Definizione: Un template è un modello che permette al compilatore di generare automaticamente versioni specifiche di funzioni o classi per i tipi richiesti.
Perché usare i template?
- Eliminano la ridondanza: un’unica funzione può operare su più tipi (es.
int,double,string). - Aumentano la sicurezza del tipo: controlli avvengono in fase di compilazione.
- Migliorano la riusabilità: lo stesso codice funziona per tipi diversi.
- Performance ottimizzate: il compilatore genera codice specifico per ogni tipo, senza costi di runtime.
Come funziona la compilazione dei template
Durante la compilazione:
- Il compilatore non genera immediatamente il codice per un template.
- Quando il template viene usato con un tipo concreto, il compilatore istanzia una versione specifica.
- Ogni istanziazione è una copia indipendente del codice adattata al tipo scelto.
Esempio:
somma(3, 4); // genera somma<int>(int, int)
somma(2.5, 1.5); // genera somma<double>(double, double)
2. Template di Funzione
Un function template permette di scrivere funzioni che lavorano con tipi diversi.
Esempio base
#include <iostream>
using namespace std;
template <typename T>
T somma(T a, T b) {
return a + b;
}
int main() {
cout << somma(3, 7) << endl; // int
cout << somma(2.5, 3.5) << endl; // double
return 0;
}
template <typename T>definisce un parametro di tipo generico.- Il compilatore genera automaticamente le versioni int, double, ecc.
Suggerimento
Possibile usare anche template <class T>, è equivalente.
3. Template di Classe
Un class template consente di creare strutture dati generiche.
#include <iostream>
using namespace std;
template <typename T>
class Scatola {
private:
T contenuto;
public:
Scatola(T c) : contenuto(c) {}
T get() { return contenuto; }
};
int main() {
Scatola<int> s1(42);
Scatola<string> s2("Ciao Template");
cout << s1.get() << endl;
cout << s2.get() << endl;
/*
Output:
42
Ciao Template
*/
}
Nota
Ogni volta che si istanzia Scatola<T>, il compilatore crea una versione specifica per il tipo richiesto.
Vantaggi dei class template:
- Consentono la creazione di contenitori generici (
vector,map,set). - Permettono riuso e coerenza del codice.
- Offrono type safety: il tipo è verificato dal compilatore.
4. Template con più parametri
Puoi definire più parametri di tipo:
#include <iostream>
using namespace std;
template <typename T, typename U>
void stampa(T a, U b) {
cout << a << " e " << b << endl;
}
int main() {
stampa(10, 3.14);
stampa("C++", 2025);
/*
Output:
10 e 3.14
C++ e 2025
*/
}
5. Parametri di default nei Template
È possibile definire tipi di default per i parametri template:
template <typename T = int>
class Valore {
T dato;
public:
Valore(T d) : dato(d) {}
void mostra() { std::cout << dato << std::endl; }
};
int main() {
Valore<> v1(5); // Usa int di default
Valore<double> v2(3.14);
v1.mostra();
v2.mostra();
}
6. Specializzazione dei Template
La specializzazione permette di personalizzare il comportamento per un tipo specifico.
#include <iostream>
using namespace std;
template <typename T>
void mostra(T x) {
cout << "Generico: " << x << endl;
}
// Specializzazione per string
template <>
void mostra<string>(string x) {
cout << "Stringa: " << x << endl;
}
int main() {
mostra(10);
mostra(string("Ciao"));
/*
Output:
Generico: 10
Stringa: Ciao
*/
}
7. Template e Funzioni Membro
Una classe template può avere metodi template:
#include <iostream>
using namespace std;
template <typename T>
class Wrapper {
public:
T valore;
Wrapper(T v) : valore(v) {}
template <typename U>
void combina(U altro) {
cout << valore + altro << endl;
}
};
int main() {
Wrapper<int> w(10);
w.combina(5); // 15
w.combina(2.5); // 12.5
}
8. Template Avanzati
Con C++17 e C++20, i template sono diventati ancora più potenti.
8.1 Template Template Parameters
#include <iostream>
#include <vector>
using namespace std;
template <template <typename, typename> class Container, typename T>
class Gestore {
Container<T, allocator<T>> dati;
public:
void aggiungi(T val) { dati.push_back(val); }
void mostra() {
for (auto& el : dati) cout << el << " ";
cout << endl;
}
};
int main() {
Gestore<vector, int> g;
g.aggiungi(1);
g.aggiungi(2);
g.mostra();
}
8.2 Concepts (C++20)
I concepts permettono di specificare vincoli sui tipi nei template:
#include <concepts>
#include <iostream>
using namespace std;
template <std::integral T>
T quadrato(T x) {
return x * x;
}
int main() {
cout << quadrato(5) << endl; // OK
// cout << quadrato(3.14); // Errore: non è integrale
}
Suggerimento
I concepts rendono il codice più leggibile e i messaggi d’errore più chiari!
9. Esempio pratico: Stack generico
#include <iostream>
#include <vector>
using namespace std;
template <typename T>
class Stack {
vector<T> elementi;
public:
void push(T val) { elementi.push_back(val); }
void pop() { if(!elementi.empty()) elementi.pop_back(); }
T top() { return elementi.back(); }
bool vuoto() { return elementi.empty(); }
};
int main() {
Stack<int> s;
s.push(10);
s.push(20);
cout << s.top() << endl; // 20
s.pop();
cout << s.top() << endl; // 10
}
10. Esercizi
10.1 Esercizio - Funzione Generica maxGenerico
Crea una funzione template maxGenerico che:
- prenda due parametri di tipo generico
T, - restituisca il valore maggiore tra i due,
- funzioni correttamente con tipi numerici e stringhe.
Esempio d’uso:
cout << maxGenerico(10, 25) << endl; // 25
cout << maxGenerico(3.5, 2.1) << endl; // 3.5
cout << maxGenerico(string("Ciao"), string("Mondo")) << endl; // Mondo
10.2 Esercizio - Classe Template Coppia
Crea una classe template Coppia<T1, T2> che rappresenti una coppia di valori (di tipi potenzialmente diversi).
La classe deve:
- avere due attributi privati primo e secondo,
- un costruttore per inizializzarli,
- un metodo
mostra()che stampi i due valori, - un metodo
scambia()che inverta i valori (solo seT1eT2sono uguali).
Esempio d’uso:
Coppia<int, string> c1(5, "elementi");
c1.mostra(); // (5, elementi)
Coppia<int, int> c2(10, 20);
c2.scambia();
c2.mostra(); // (20, 10)
10.3 Esercizio - Stack Generico
Crea una classe template Stack<T> che funzioni come una pila (LIFO).
La classe deve fornire:
- un metodo
push(T)per aggiungere un elemento, - un metodo
pop()per rimuovere l’ultimo elemento, - un metodo
top()per ottenere l’ultimo elemento inserito, - un metodo
vuoto()che restituisce true se lo stack è vuoto.
Esempio d’uso:
Stack<int> s;
s.push(10);
s.push(20);
cout << s.top() << endl; // 20
s.pop();
cout << s.top() << endl; // 10
11. Quiz a risposta multipla
Mettiti alla prova
0/5 risposte
1) Cosa permette di fare un template in C++?
2) Qual è la sintassi corretta per dichiarare un template di funzione?
3) Cosa fa la specializzazione di un template?
4) Cosa restituisce find() in una std::map o std::set?
5) Qual è lo scopo dei 'concepts' in C++20?