corso ASD
Corso di Algoritmi e Strutture Dati a.a. 2013/2014

Esercizio 07

Si consideri le seguenti indicazioni sui template, commentate a lezione. Successivamente ci si colleghi con il repository:
https://code.google.com/p/asd-dib/
si eseguano le istruzioni per configurare correttamente eclipse e scaricare il repository.

Il repository fa uso intensivo di template. In questa sezione sono date informazioni basilari per comprendere cosa sono e a cosa servono. Dopo aver verificato che si riesce a compilare correttamente il repository effettuare uno studio approfondito del codice ivi contenuto, sarà oggetto della prossima esercitazione.
Dopo aver realizzato tutti i punti richiesti in questa esercitazione, inviare all'indirizzo paolo.buono@uniba.it l'esercitazione in una cartella compressa in formato zip. Il file deve essere chiamato: "[ASDBR1314] esercizio07 - cognome.zip" e deve contenere solo file .h, .cpp, e il file di progetto (NO .exe). Scadenza dell'invio dell'esercitazione: 23.59 di giovedì 12 dicembre.

Template

Un template (talvolta chiamato modello) è una formula astratta per produrre codice concreto, si utilizza per le classi e per le funzioni. Il compilatore instanzierà la funzione/classe in fase di run-time, prima di allora sarà una funzione/classe generica. Lo stesso template può essere usato per generare istanze differenti di classi, la differenza sta nei parametri del template, che, agiscono allo stesso modo in cui agiscono i parametri per le funzioni ordinarie. Mentre i parametri ordinari sono dei segnaposto per le classi, i parametri dei template sono segnaposto per tipi di dato e per classi.

La possibilità offerta dal C++ di instanziare i template è una caratteristica che distingue questo linguaggio da altri (in C# e in Java esistono i Generics, che rispetto ai template C++ hanno dei limiti, si veda un post su stackoverflow per una spiegazone sulle differenze).

Ora la motivazione per l'uso dei template. Negli algoritmi di ordinamento è necessario fare lo scambio di coppie di elementi, questo scambio può essere demandato a funzioni esterne, come nel seguente caso:

void swap (int& m, int& n){
    int temp = m;
    m = n;
    n = temp;
}

Se i due parametri sono stringhe, si dovrebbe usare:

void swap (string& s1, string& s2){
    string temp = s1;
    s1 = s2;
    s2 = temp;
}

L'unica differenza tra le due sta nel tipo di parametro (o oggetti) passato, il resto non cambia. Se l'ordinamento deve essere effettuato con altri tipi di dato si creeranno altre funzioni swap, ognuna per il tipo di dato che si vuole ordinare. Questo risulta molto inefficiente. Per evitare la ridondanza si utilizzano i template, come nel seguente esempio:

Se i due parametri sono stringhe, si dovrebbe usare:

template <class T>
void swap (T& x, T& y){
    T temp = x;
    x = y;
    y = temp;
}

Il simbolo T è detto parametro di tipo, che rappresenta il segnaposto da rimpiazzare con il tipo di dato scelto (int, string, ...) per effettuare lo scambio. Oltre alla sostituzione del tipo di dato con T (simbolo che convenzionalmente è denominato con T, che sta anche per Template o anche per Tipo, ma che può assumere un qualsiasi nome) c'è un'altra differenza: la dichiarazione template <class T>. class sta per 'qualunque tipo'.

Così come una funzione accetta più parametri, un template può avere più parametri, che saranno separati da virgola e chiamati ognuno con un simbolo proprio, per esempio: template <class T, class U, class V>.

Per quanto riguarda la 'chiamata' dei template, questa è fatta come si fa per le funzioni, nel caso della funzione swap:

int m = 2, n=3;
swap (m, n);
string (s1 = "pippo", s2 = "pluto");
swap (s1, s2);
Rational x(1/3), y(2/5);
swap (x, y);

Per ogni differente chiamata il compilatore creerà le funzioni distinte, sostituendo il parametro di tipo con il tipo scelto per usare tale funzione.

Un template di classe opera allo stesso modo del template di funzione, anziché generare funzioni genererà classi. La sintassi è la seguente:

template <class T, ...> class X{ ... };

Alcuni parametri possono essere normali parametri, non è detto che debbano tutti essere template:

template <class T, int n, class U> class X{ ... };

Un'accortezza da avere è che, il compilatore istanzia i template in fase di compilazione, per questa ragione non possono essere passate ai template di classe variabili ai parametri ordinari, es:

template <class T, int n>
class X{};
int main(){
    X<float, 3> x;
    const int n;
    X<char, n> y;
    int i = 66;
    X<short, i> z; //errore: i non costante
}

Note:

Esercizi:

corso ASD