C++ Template

Da Andreabont's Wiki.

Un template è una porzione di codice (sia funzione che classe) generica rispetto ai tipi di dato che tratta. E' spesso utile che un algoritmo possa lavorare su tipi di dato differenti, per farlo sarebbe necessario creare una versione del algoritmo per ogni dato supportato e usare l'overloading. Per evitare questo è possibile sfruttare i template, che descrivono questo algoritmo in modo indipendente dal tipo, lasciando al compilatore il compito di generare le varie versioni necessarie. Da notare che il template ha minore priorità rispetto ad altre funzioni in overloading scritte esplicitamente. Nel caso esista una funzione per uno specifico tipo di dato sarà preferita quella rispetto al template, secondo l'uso della specializzazione completa. E' anche possibile effettuare una specializzazione parziale, mantenendo sempre una struttura a template con minori parametri di quella considerata generica. Questa avrà maggior priorità del template generico, ma minore priorità di una specializzazione completa.

Nota: Un template va sempre dichiarato nel file header.

Esempio funzione

template <typename X>
void swap(X &a, X &b) {
   X temp;
   temp = a;
   a = b;
   b = temp;
}

Si nota il placeholder X, che indica il tipo di dato generico. Può essere usato qualsiasi testo, nel nostro esempio usiamo la lettera X.

Meta-programmazione

I template in C++ sono turing completi, in questa sezione vedremo come implementare i principali costrutti.

Costrutto IF

A causa del fatto che lo standard C++ non permette la specializzazione parziale delle funzioni, questo costrutto è implementabile solo da struct/class.

template<int P, bool= P>=8>
struct my
{
    inline static void foo()
    {
        cout << P << " TRUE" << endl;
    }
};
 
template<int P>
struct my<P,false>
{
    inline static void foo()
    {
        cout << P << " FALSE" << endl;
    }
};

Ricorsione

template <int N>
struct Factorial 
{
    enum { value = N * Factorial<N - 1>::value };
};

template <>
struct Factorial<0> 
{
    enum { value = 1 };
};