Lllezione 12 Template Template Lezione 12 ü Il template è un meccanismo che consente di creare uno schema generico di funzione o di classe, che non fa esplicito riferimento a nessun particolare tipo di dati ® utile quando si devono implementare più funzioni o classi che si comportano allo stesso modo ma lavorano su dati di tipo diverso ü Il template consente di progettare solo uno schema generale per implementare una particolare operazione ® Il compilatore provvede a produrre da questo schema il codice effettivo per implementare l’operazione su ogni tipo di dati (predefinito o definito dall’utente) Laboratorio di Algoritmi e Strutture Dati 2001 -02 Cosa è un Template 1 Laboratorio di Algoritmi e Strutture Dati 2001/02 1 Lllezione 12 Template ü Il template di funzione è uno schema di funzione generica, che non fa esplicito riferimento a nessun particolare tipo di dati input ® consente di progettare un’unica funzione per implementare una particolare operazione ü All’interno del codice del programma di sarà una diversa funzione per implementare l’operazione su ogni tipo di dati ® ® La generazione di tutte le funzioni è a carico del compilatore Il compilatore provvede a produrre da questo schema una diversa funzione per ogni tipo di dati Laboratorio di Algoritmi e Strutture Dati 2001 -02 Cosa è un Template di Funzione 2 ü Il template di classe è uno schema di classe generica, che non fa esplicito riferimento a nessun particolare tipo di dati membro ® consente di progettare un’unica classe per implementare un tipo di dato astratto, indipendente dal tipo di dato contenuto al suo interno ü All’interno del codice del programma ci sarà una diversa classe per implementare il tipo di dato astratto per ogni possibile tipo di dato membro ® ® La generazione di tutte le classi e dei suoi metodi è a carico del compilatore Il compilatore provvede a produrre da questo schema una diversa classe per ogni tipo di dato membro Laboratorio di Algoritmi e Strutture Dati 2001 -02 Cosa è un Template di Classe 3 Laboratorio di Algoritmi e Strutture Dati 2001/02 2 Lllezione 12 Template ü L’overloading consente di assegnare lo stesso nome a funzioni differenti ® ® il programmatore deve scrivere tutte le funzioni semplificazione esclusivamente lessicale (assegna un nome ad ogni operazione logica) ü Il template è uno schema di funzione che può essere applicato su diversi dati ® ® il programmatore deve scrivere una sola funzione tutte le versioni ricavate dallo schema devono avere la stessa implementazione e differire solo per il tipo dei dato su cui operano Laboratorio di Algoritmi e Strutture Dati 2001 -02 Template e Overloading 4 ü Molti linguaggi di programmazione hanno meccanismi che consentono di scrivere delle funzioni generiche ® In C è possibile usare le macro per produrre funzioni generiche #define max(a,b) ((a)>(b)) ? (a) : (b) ü Le macro effettuano una sostituzione testuale degli argomenti con i valori passati nella chiamata alla macro ® nessun controllo sui tipi ® il compilatore non è in grado di supportare il controllo sui tipi Laboratorio di Algoritmi e Strutture Dati 2001 -02 Schemi di Funzione in C 5 Laboratorio di Algoritmi e Strutture Dati 2001/02 3 Lllezione 12 Template Quando Creare Template di Funzioni versioni della stessa funzione che lavorano su dati di tipo diverso ® Operano tutte alla stessa maniera ma usano variabili di tipo diverso int max(int, int); // massimo tra due interi char max(char, char); // massimo in un vettore di interi double max(double, double); // massimo tra due double ü Si possono utilizzare i template di funzioni per creare librerie di funzioni generiche ® l’utente della libreria potrà utilizzare la libreria su qualunque tipo di dati Laboratorio di Algoritmi e Strutture Dati 2001 -02 ü Creare un template di funzioni se si devono usare più 6 Definizione di un Template definito prima di essere utilizzato dal programma ü La definizione (dichiarazione) di un template di funzione è una definizione (dichiarazione) di una funzione parametrizzata template <class T> T max( T* a, int dim) { \\ max in un array (di ogni tipo) T tmp = a[0]; for( int i = 1; i < dim; i++ ) if( a[i] > tmp ) tmp = a[i]; return tmp; } Laboratorio di Algoritmi e Strutture Dati 2001 -02 ü Il template di una funzione deve essere dichiarato o 7 Laboratorio di Algoritmi e Strutture Dati 2001/02 4 Lllezione 12 Template Parametri del Template deve specificare la lista dei parametri, tra <> ® Parametri rispetto ai quali è descritto il comportamento della funzione ü Un parametro può essere ® un tipo (parametro di tipo) w Preceduto dalle parole class o typename ® un’espressione costante (parametro di valore) w Preceduta dal tipo del risultato dell’espressione template <class T, int size> T max( T (&a)[size]) { \\ max in un array di dimensione size di tipo T } Laboratorio di Algoritmi e Strutture Dati 2001 -02 ü Nella definizione (dichiarazione) di un template si 8 ü La parola riservata template e la lista dei parametri del template sono obbligatori ® Ogni parametro deve essere preceduto dal suo tipo w class (typename) tipo predefinito (definito dall’utente) ® Tutti i parametri devono avere nomi distinti ® Ogni parametro deve comparire nella firma della funzione ® Il nome del parametro non può essere ridefinito nella funzione Laboratorio di Algoritmi e Strutture Dati 2001 -02 Corretta Definizione di un Template 9 Laboratorio di Algoritmi e Strutture Dati 2001/02 5 Lllezione 12 Template template <class T, class T> T f(T, T); // ERRORE template <class T, U> void f(T, U); // ERRORE template <class T, typename U> void f(T, U); // CORRETTO template <class T, class U> U f(T, T); // ERRORE template <class T> T f(T, T) { typedef double T; … } // ERRORE Laboratorio di Algoritmi e Strutture Dati 2001 -02 Esempi Dichiarazioni di Template 10 ü Lo standard C++ supporta l’inizializzaione per default dei parametri di un template Valgono le stesse regole per l’inizializzazione per default dei parametri di una funzione ® Non tutti i compilatori supportano questa proprietà ® üI compilatori pre-standard non supportano l’inizializzazione per default dei parametri del template Laboratorio di Algoritmi e Strutture Dati 2001 -02 Inizializzazione di Default dei Parametri del Template 11 Laboratorio di Algoritmi e Strutture Dati 2001/02 6 Lllezione 12 Template Istanziazione di un Template template non alloca nessuna memoria ® ® non è in grado di calcolare la dimensione del record di attivazione non sa come implementare la funzione parametrizzata ü La definizione delle varie istanze di funzioni ricavate dal template (istanziazione del template) avviene solo quando queste funzioni vengono utilizzate ® ® Funzione invocata dal programma assegnamento dell’indirizzo della funzione ad un puntatore ü l'istruzione che provoca l'istanziazione è detta punto di Laboratorio di Algoritmi e Strutture Dati 2001 -02 ü Quando il compilatore legge la definizione di un istanziazione 12 Istanziazione di un Template ricavate dal template il compilatore opera nel seguente modo: 1. 2. 3. 4. 5. sospende la compilazione, recupera la definizione del template, deduce dalla chiamata i tipi ed i valori dei parametri sostituisce ai parametri del template i tipi ed i valori dedotti, definisce la funzione così ottenuta ü L’istanziazione avviene soltanto la prima volta che una funzione viene invocata ® le chiamate successive sono implementate normalmente Laboratorio di Algoritmi e Strutture Dati 2001 -02 ü Quando il programma invoca una delle funzioni 13 Laboratorio di Algoritmi e Strutture Dati 2001/02 7 Lllezione 12 Template template <class T> T max(T*, int); int ai[4] = { 12, 8, 73, 45 }; int main() { int size = sizeof (ai) / sizeof (ai[0]); cout << "massimo di ai è: " << max( ai, size ) << endl; // istanzia max(int*, int) } Laboratorio di Algoritmi e Strutture Dati 2001 -02 Esempio Istanziazione Template 14 Deduzione degli Argomenti dagli argomenti della chiamata i tipi ed i valori da attribuire ai parametri del template per ogni prima occorrenza di un parametro del template nella lista dei parametri della funzione, assegna al parametro il tipo del corrispondente argomento della chiamata template <class T, class U> void f(T, U, T); f(0, ‘a’, 10); \\ genera f(int, char, int) f(0, ‘a’, 3.14); \\ ERRORE ® ü tutti gli argomenti parametrizzati devono corrispondere esattamente al tipo assegnato al parametro ü il tipo del risultato non conta per la deduzione Laboratorio di Algoritmi e Strutture Dati 2001/02 Laboratorio di Algoritmi e Strutture Dati 2001 -02 ü E’ il processo attraverso il quale il compilatore ricava 15 8 Lllezione 12 Template ü Quando il compilatore legge una chiamata ad un template di funzione opera nel seguente modo ® ® ® ® Controlla che ogni parametro del template compaia compaia come parametro della funzione cerca nella firma la prima occorrenza di ogni parametro del template e gli assegna il tipo o il valore dell'argomento corrispondente controlla che tutte le altre occorrenze del parametro del template corrispondano esattamente (anche con corrispondenze banali) con i corrispondenti argomenti cerca una corrispondenza tra i parametri della funzione non parametrizzati ed i corrispondenti argomenti ü Se il compilatore non è in grado di dedurre il tipo di un Laboratorio di Algoritmi e Strutture Dati 2001 -02 Algoritmo per Istanziazione parametro del template segnala un ambiguità 16 template <typename Type, int size> Type min( Type (&r_array)[size] ) { Type min_val = r_array[0]; for ( int i = 1; i < size; ++i ) if ( r_array[i] < min_val ) min_val = r_array[i]; return min_val; } int ia[] = { 10, 7, 14, 3, 25 }, ia2[5] = { 10, 15, 2, 20, 16 }, *ptr; double da[6] = { 10.2, 7.1, 14.5, 3.6, 25.4 }; … int *ptr = ia; int i = min( ia ); i = min( ia2 ); i = min(ptr); i = min( da ); … // istanzia min(int(&)[5]) // invoca la funzione min(int(&)[5] // ERRORE // istanzia min(double(&)[6]) Laboratorio di Algoritmi e Strutture Dati 2001/02 Laboratorio di Algoritmi e Strutture Dati 2001 -02 Esempio 17 9 Lllezione 12 Template ü Nell’invocare un template di funzione è possibile indicare esplicitamente il valore di un parametro del template ® ® il compilatore non esegue l'algoritmo di deduzione ed accetta la scelta del programmatore Utile per risolvere le situazioni di ambiguità template <class T> T min(T, T); int main() { unsigned int ui = 1024; min(ui, 1024); // ERRORE min<int>(ui, 1024); // istanzia min(int, int) min<unsigned int>(ui, 1024); } Laboratorio di Algoritmi e Strutture Dati 2001 -02 Istanziazione Esplicita 18 ü Utilizzando l'istanziazione esplicita parametrizzare anche il tipo del risultato ® è possibile istanziazioni di questo template sono corrette solo se esplicite template <class T1, class T2, class T3> T1 min(T2, T3); ü per le istanziazioni dei parametri del template valgono le stesse regole dell'inizializzazione dei parametri di funzione per default char c; unsigned int ui; unsigned int ris = min(c, ui); // ERRORE ris = min<unsigned int, char, unsigned int>min(c, ui); ris = min<unsigned int>min(c, ui); Laboratorio di Algoritmi e Strutture Dati 2001 -02 Tipo del Risultato Parametrizzato 19 Laboratorio di Algoritmi e Strutture Dati 2001/02 10 Lllezione 12 Template ü L'istanziazione esplicita può essere usata per eliminare l'ambiguità presente nella chiamata ad una funzione che ha argomenti parametrizzati template <class T> T f(T); void g(int(*)(int)); void g(double(*)(double)); main() { g(&f); g(&f<int(*)(int)>); } // ERRORE Laboratorio di Algoritmi e Strutture Dati 2001 -02 Risoluzione Ambiguità 20 ü E’ possibile creare versioni sovrapposte di template di funzioni diversi template svolgono la stessa operazione logica ma in modi differenti ® tutte le istanze prodotte dai vari template devono differire tra loro per numero o tipo di argomenti ® ü Ogni istanza di un template è una funzione del programma che deve avere una firma che la identifica univocamente Laboratorio di Algoritmi e Strutture Dati 2001 -02 Overloading di Template 21 Laboratorio di Algoritmi e Strutture Dati 2001/02 11 Lllezione 12 Template template <class T> T min(T, T); template <class T> T min(const T*, int); template <typename T> T min(const vector<T>&); int i = 0, ia[10]; i = min(3, 5); // corrisponde alla prima funzione i = min(ia, 10); // corrisponde alla seconda funzione template <class T, class U> int min(T, U); i = min(3, 5); // ambigua, perché? Laboratorio di Algoritmi e Strutture Dati 2001 -02 Esempio Overloading di Template 22 Specializzazione di Template fornita dal template di funzione può essere scorretta o inefficiente ü E' possibile definire un’eccezione al template ® Lo schema generale del template viene utilizzato per generare funzioni per tutti i tipi di dati tranne quelli per cui sono specificate le eccezioni ü Per i tipi che fanno eccezione devono essere definite delle specializzazioni del template ® si può specializzare un template solo dopo aver dichiarato lo schema generale Laboratorio di Algoritmi e Strutture Dati 2001 -02 ü Per alcuni tipi di dati la versione generale 23 Laboratorio di Algoritmi e Strutture Dati 2001/02 12 Lllezione 12 Template Specializzazione Esplicita di Template definizione di una specializzazione è una definizione di un template con i parametri istanziati template <class T> T max(T, T); typedef const char* PCC; template <> PCC max<PCC>(PCC s1, PCC s2) { return(strcmp(s1, s2) > 0 ? s1 : s2); } int main() { const char* p = max("ciao", "mondo"); // chiama la specializzazione e non istanzia il template } Laboratorio di Algoritmi e Strutture Dati 2001 -02 ü La 24 ü La dichiarazione di una specializzazione deve precedere la prima chiamata alla funzione ® al momento della chiamata il compilatore deve sapere che deve usare la specializzazione invece del template ü La dichiarazione di una specializzazione deve essere inclusa in tutti specializzazione ® ® i file in cui viene utilizzata la non è possibile usare in un file la specializzazione e in un altro file istanziare il template conviene inserire la dichiarazione del template e delle sue specializzazioni nello stesso header file Laboratorio di Algoritmi e Strutture Dati 2001 -02 Utilizzo delle Specializzazioni 25 Laboratorio di Algoritmi e Strutture Dati 2001/02 13 Lllezione 12 Template template <class T> T max(T, T); int main() { int i = max( 10, 5 ); // istanzia max( int, int ); const char *p = max( "ciao", "mondo" ); // istanzia const char* max( const char*, const char* ) cout << "i: " << i << " p: " << p << endl; return 0; } typedef const char* PCC; template<> PCC max<PCC>(PCC s1, PCC s2) { … } // ERRORE, doppia definizione Laboratorio di Algoritmi e Strutture Dati 2001 -02 Specializzazione Esplicita di Template 26 Specializzazione Implicita di Template un'istanza del template è una specializzazione implicita sulle chiamate a questa funzione non valgono le regole restrittive della deduzione dei parametri del template ® la definizione di una specializzazione implicita deve precedere la sua istanziazione template <class T> T min(T, int); ® int min(unsigned int,int); … int i = min(3u,i); // viene chiamata la funzione ordinaria min Laboratorio di Algoritmi e Strutture Dati 2001/02 Laboratorio di Algoritmi e Strutture Dati 2001 -02 ü Una funzione che abbia la stessa firma di 27 14 Lllezione 12 Template ü Nella risoluzione di un overloading il compilatore può istanziare funzioni da un template anche se non esplicitamente invocate ® ® nel creare l'insieme dei candidati istanzia tutte le funzioni che possono essere dedotte dagli argomenti della chiamata la funzione istanziata sarà realmente invocata solo se è la migliore funzione utilizzabile template <class T> T sum(T, int); double sum(double, double); sum(3.14, 0); // istanzia ed invoca sum(double, int) Laboratorio di Algoritmi e Strutture Dati 2001 -02 Risoluzione dell’Overloading e Istanziazioni 28 ü Se un template ha delle specializzazioni implicite ® ® nella lista delle funzioni candidate viene inserita sia la specializzazione che la funzione istanziata dal template la specializzazione è preferita rispetto alla funzione istanziata template <class T> T min(T, T); int min(int, int); min(3, 2); /* la specializzazione e l'istanza del template sono candidate la specializzazione è invocata */ Laboratorio di Algoritmi e Strutture Dati 2001 -02 Risoluzione dell’Overloading e Specializzazioni Implicite 29 Laboratorio di Algoritmi e Strutture Dati 2001/02 15 Lllezione 12 Template ü Se un template ha delle specializzazioni esplicite ® ® nella lista delle funzioni candidate viene inserita la specializzazione e non la funzione istanziata dal template la specializzazione è una candidata solo se la sua firma può essere dedotta dalla chiamata template <class T> T min(T, T); template <> double min<double>(double, double); int min(int, int); min(3.14, 2); // no match min(3.14, 2.5); // la specializzazione è candidata Laboratorio di Algoritmi e Strutture Dati 2001 -02 Risoluzione dell’Overloading e Specializzazioni Esplicite 30 1. Costruisce l'insieme delle funzioni candidate ® ® funzioni con lo stesso nome della funzione chiamata istanze di template con lo stesso nome della funzione chiamata e che possono essere dedotte dalla chiamata 2. Costruisce l'insieme delle funzioni utilizzabili ® seleziona le funzioni candidate i cui parametri corrispondono per tipo e numero agli argomenti della chiamata 3. Classifica il tipo di corrispondenza di ogni funzione utilizzabile 4. Seleziona la migliore funzione utilizzabile ® ® ® se ne esiste una sola la chiamata è risolta se ce ne sono più di una la chiamata è ambigua se non ce ne sono la chiamata non è risolta Laboratorio di Algoritmi e Strutture Dati 2001 -02 Risoluzione di una Chiamata ad una Funzione 31 Laboratorio di Algoritmi e Strutture Dati 2001/02 16 Lllezione 12 Template template <class T> T min(T, T); double min(double, double); main() { int i; double d; float f; min(0, i); // due candidate, invoca l'istanza del template per T = int min(3.14, d); // invoca la specializzazione min(0, f); // specializzazione unica candidata } char min(char, char); // cosa succede alla terza chiamata? Laboratorio di Algoritmi e Strutture Dati 2001 -02 Esempio 32 Quando Creare Template di Classi contenitore che possono essere utilizzate per contenere qualunque tipo di dati template <class T> class Coda{ T* vett; … }; ü Si possono utilizzare i template di classi per creare librerie di classi generiche ® l’utente della libreria potrà utilizzare la classe della libreria Laboratorio di Algoritmi e Strutture Dati 2001 -02 ü Un template di classe permette di creare classi istanziandola per qualunque tipo di dati 33 Laboratorio di Algoritmi e Strutture Dati 2001/02 17 Lllezione 12 Template Definizione di un Template di Classi strutturata come la definizione di una classe normale ® ® contiene lista dei parametri del template i parametri possono essere utilizzati nella definizione template <class T> class Coda { public: Coda(); ~Coda(); void inserisci( const T& ); T& rimuovi(); bool vuota(); private: … }; Laboratorio di Algoritmi e Strutture Dati 2001 -02 ü La definizione (dichiarazione) di un template di classi è 34 template <class T> class CodaItem { public: friend class Coda<T>; CodaItem(const T&); private: CodaItem<T>* succ; T item; }; template <class T> class Coda { public: Coda(); ~Coda(); void inserisci( const T& ); T& rimuovi(); bool vuota(); private: CodaItem<T>* testa; CodaItem<T>* coda; }; Laboratorio di Algoritmi e Strutture Dati 2001 -02 Definizione Classe Coda 35 Laboratorio di Algoritmi e Strutture Dati 2001/02 18 Lllezione 12 Template ü Quando il compilatore legge la definizione di un template di classi non alloca memoria ü Un’istanza del template viene creata solo quando il programma definisce una variabile della classe ® ® per definire una variabile della classe bisogna specificare tutti i valori da assegnare ai parametri del template La definizione di un puntatore o un riferimento non istanzia il template Coda<int> qi; Coda<string> qs; Coda<double>* pqd; Coda q; // non istanzia il template // ERRORE Laboratorio di Algoritmi e Strutture Dati 2001 -02 Istanziazione di un Template di Classi 36 ü L’istanziazione di un template può essere utilizzato come specificatore di tipo ü Non è possibile far riferimento al template della classe al di fuori dello scope del template Laboratorio di Algoritmi e Strutture Dati 2001 -02 Istanziazione di un Template di Classi 37 Laboratorio di Algoritmi e Strutture Dati 2001/02 19 Lllezione 12 Template ü Il punto di istanziazione di un template è il momento in cui viene generata la classe ® ® Definizione di una variabile Dereferenziazione di un puntatore o di un riferimento ü Nel punto di istanziazione del template deve essere visibile la definizione del template ® Nel C++ pre-standard dovevano essere visibili anche le definizioni dei metodi ü La definizione di una classe va inserita in un file di intestazione mentre le definizioni dei suoi metodi vanno inseriti in un file di implementazione ® Ogni file in cui si istanzia il template include la definizione della classe Laboratorio di Algoritmi e Strutture Dati 2001 -02 Punto di Istanziazione di un Template di Classi 38 ü I metodi di un template di classi sono template di funzioni ® Possono essere definiti inline all’interno della definizione del template o esterni alla definizione template <class T> class Coda { public: Coda() : testa(0), coda(0) {}; ~Coda(); void inserisci( const T& ); T& rimuovi(); bool vuota() { return front == 0; } private: CodaItem<T>* testa; CodaItem<T>* coda; }; Laboratorio di Algoritmi e Strutture Dati 2001/02 Laboratorio di Algoritmi e Strutture Dati 2001 -02 Metodi di Template di Classi 39 20 Lllezione 12 Template template <class T> Coda<T>::~Coda() { while( !vuota() ) rimuovi(); } template <class T> void Coda<T>::inserisci(const T& val) { CodaItem<T> *pt = new CodaItem<T>(val); if(vuota()) testa = coda = pt; else { coda->succ = pt; coda = pt; } } Laboratorio di Algoritmi e Strutture Dati 2001 -02 Metodi di Template di Classi 40 template <class T> T& Coda<T>::rimuovi() { if(vuota()) { cerr << “coda vuota” << endl; exit(-1); } CodaItem<T> *pt = testa; testa = testa->succ; T val = pt->item; delete pt; return val; } Laboratorio di Algoritmi e Strutture Dati 2001 -02 Metodi di Template di Classi 41 Laboratorio di Algoritmi e Strutture Dati 2001/02 21 Lllezione 12 Template ü Esistono tre tipi di dichiarazioni di amicizia che possono com parire nella definizione di un template di classi class F; template <class T> class CodaItem { friend class F; friend void f(); friend void F::f(); }; ü Le classi e le funzioni non template sono amiche di ogni Laboratorio di Algoritmi e Strutture Dati 2001 -02 Relazioni di Amicizia per Template di Classi istanza del template 42 ü I metodi di un template di classi vengono istanziati quando sono invocati per la prima volta ® L’istanziazione dei metodi segue le dell’istanziazione dei template di funzioni regole ü Il C++ pre-standard istanzia tutti i metodi del template di classi contemporaneamente alla istanziazione della classe Laboratorio di Algoritmi e Strutture Dati 2001 -02 Istanziazione dei Metodi di un Template di Classi 43 Laboratorio di Algoritmi e Strutture Dati 2001/02 22 Lllezione 12 Template template <class T> class F; template <class T> void f(CodaItem<T>); template <class T> class Coda { friend class F<T>; friend void f(CodaItem<T>); friend void F<T>::f(); }; Ogni istanza della classe F è amica della corrispondente classe Coda Laboratorio di Algoritmi e Strutture Dati 2001 -02 Relazioni di Amicizia per Template di Classi 44 template <class T> class CodaItem { template <class U> friend class F; template <class U> friend void f(CodaItem<U>); template <class U> friend void F<U>::f(); }; Tutte le istanze della classe F sono amiche di ogni istanza della classe CodaItem Laboratorio di Algoritmi e Strutture Dati 2001 -02 Relazioni di Amicizia per Template di Classi 45 Laboratorio di Algoritmi e Strutture Dati 2001/02 23 Lllezione 12 Template template <class T> class CodaItem { friend class Coda<T>; friend ostream& operator<<(ostream&, CodaItem<T>&); private: CodaItem(const T&); CodaItem<T>* succ; T item; }; Laboratorio di Algoritmi e Strutture Dati 2001 -02 Relazioni di Amicizia tra Coda e CodaItem 46 template <class T> ostream& operator<<( ostream &os, const CodaItem<T> &qi ) { os << qi.item; return os; } template <class T> ostream& operator<<( ostream &os, const Coda<T> &q ) { os << "< "; CodaItem<T> *p; for ( p = q.testa; p; p = p->succ ) os << *p << " "; os << " >"; return os; } Laboratorio di Algoritmi e Strutture Dati 2001/02 Laboratorio di Algoritmi e Strutture Dati 2001 -02 Output di Coda e CodaItem 47 24 Lllezione 12 Template ü Un template di classi può dichiarare dei membri static ® ® ogni istanza del template avrà le proprie copie dei dati static i dati static sono comuni solo tra variabili dello stesso tipo di istanziazione ü I dati static vengono istanziati solo quando vengono usati per la prima volta ü La sintassi per inizializzare un dato static di un template è template <class T> int Coda<T>::cont = 1; Laboratorio di Algoritmi e Strutture Dati 2001 -02 Elementi static di un Template 48 template <class T> class CodaItem { friend class Coda<T>; friend ostream& operator<<(ostream&, CodaItem<T>&); private: static const unsigned int _blocco; static CodaItem<T>* free_list; CodaItem(const T&); void* operator new(size_t); void operator delete(void*, size_t); CodaItem<T>* succ; T item; }; template <class T> CodaItem<T>* CodaItem<T>::free_list = 0; template <class T> const unsigned int CodaItem<T>::_blocco = 24; Laboratorio di Algoritmi e Strutture Dati 2001 -02 Membri static di CodaItem 49 Laboratorio di Algoritmi e Strutture Dati 2001/02 25 Lllezione 12 Template template <class T> void* CodaItem<T>::operator new( size_t size ) { CodaItem<T> *p; if ( ! free_list ) { size_t blo = _blocco * size; free_list = p = reinterpret_cast<CodaItem<T>* > ( new char[blo] ); for ( ; p != &free_list[ CodaItem_blocco - 1 ]; ++p ) p->succ = p + 1; p->succ = 0; } p = free_list; free_list = free_list->succ; return p; } Laboratorio di Algoritmi e Strutture Dati 2001 -02 Uso Membri static di CodaItem 50 template <class T> void CodaItem<T>::operator delete( void *p, size_t ) { static_cast< CodaItem<T>* >( p )->succ = free_list; free_list = static_cast< CodaItem<T>* > ( p ); } Laboratorio di Algoritmi e Strutture Dati 2001 -02 Uso Membri static di CodaItem 51 Laboratorio di Algoritmi e Strutture Dati 2001/02 26 Lllezione 12 Template ü Il C++ standard consente la definizione di metodi template all’interno di classi (sia template che non template) ® ® Tecnica ampiamente utilizzata nella libreria standard per supportare la programmazione generica Non supportata da compilatori pre-standard ü Ogni istanza della classe template contiene tutte le istanze del metodo template ® Il metodo template è istanziato quando viene invocato Laboratorio di Algoritmi e Strutture Dati 2001 -02 Membri Template 52 ü E’ possibile definire delle versioni specializzate del template della classe template <> class Coda<LongDouble> { … }; ® La specializzazione deve seguire la definizione del template ® La specializzazione deve essere inseritain tutti i file del programma ® In questo caso bisogna fornire le specializzazioni per tutti i metodi del template della classe ü E’ possibile definire anche solo la specializzazione di alcuni metodi della classe class LongDouble; template <> LongDouble Coda::remove() { … } Laboratorio di Algoritmi e Strutture Dati 2001 -02 Specializzazione di un Template di Classi 53 Laboratorio di Algoritmi e Strutture Dati 2001/02 27 Lllezione 12 Template ü Se il template ha più parametri è possibile fornire una specializzazione per solo uno dei parametri ® Può fornire implementazioni più efficienti per specifici valori del parametro Laboratorio di Algoritmi e Strutture Dati 2001 -02 Specializzazioni Parziali 54 ü Ogni istanza del template ha un proprio scope locale ü il compilatore cerca di risolvere, se possibile, i nomi quando legge la definizione del template ® ® ® i nomi non dipendenti dal template sono risolti subito i nomi dipendenti dal template sono risolti dopo l'istanziazione Un nome potrebbe essere risolto con una variabile non visibile al momento della definizione del template template <class T> T min(T* array, int size) { // size non dipende dal template T minVal = array[0]; // minVal dipende dal template for(int i = 1; i < size; i++) if(array[i] < minVal) minVal = array[i]; return minVal; } Laboratorio di Algoritmi e Strutture Dati 2001/02 Laboratorio di Algoritmi e Strutture Dati 2001 -02 Risoluzione dei Nomi nei Template 55 28 Lllezione 12 Template Risoluzione dei Nomi nei Template ® ® se tra gli argomenti non ci sono variabili dipendenti dal template la funzione deve essere dichiarata prima della definizione del template se tra gli argomenti ci sono variabili dipendenti dal template la funzione deve essere dichiarata prima della istanziazione del template template <class T> T min(T* array, int size) { T minVal = array[0]; // minVal dipende dal template for(int i = 1; i < size; i++) if(array[i] < minVal) minVal = array[i]; print(minVal); // print non dichiarata return minVal; } Laboratorio di Algoritmi e Strutture Dati 2001 -02 ü Quando il template contiene una chiamata a funzione 56 Modelli di Compilazione di Template momento dell'istanziazione del template il compilatore deve produrre il codice del'istanza ® ® deve conoscere la definizione del template il compilatore deve interrompere la compilazione, risolvere i valori da assegnare ai parametri e generare la classe ü La definizione di una allocazione di memoria ® classe non determina La definizione di una classe può essere inserita più volte all’interno dello stesso programma ü La definizione di un template di classe va inserita in un file di intestazione ® Il file viene incluso in tutti i file in cui deve essere istanziato il template Laboratorio di Algoritmi e Strutture Dati 2001/02 Laboratorio di Algoritmi e Strutture Dati 2001 -02 ü Al 57 29 Lllezione 12 Template ü I metodi del template di classi e i membri static si comportano come template di funzioni ® ® Le definizioni devono essere visibili nel punto in cui vengono istanziati I metodi sono istanziati solo quando vengono invocati per la prima volta ü Il C++ standard supporta due modelli di compilazione dei template di funzioni ® ® modello ad inclusione modello a separazione Laboratorio di Algoritmi e Strutture Dati 2001 -02 Modelli di Compilazione di Template 58 ü La definizione di un metodo del template deve essere inclusi in ognuno dei file in cui il template è istanziato ® ® il template viene inserito in un header file la definizione del template è trattata come le funzioni inline ü Se l'header file viene incluso in più di un file il compilatore deve generare una sola copia di ogni istanza del template ® ® L’implementazione dipende dal compilatore molti compilatori generano istanze del template in ogni file. Il linker seleziona una sola istanza e la utilizza per tutte le chiamate Laboratorio di Algoritmi e Strutture Dati 2001 -02 Modello ad Inclusione 59 Laboratorio di Algoritmi e Strutture Dati 2001/02 30 Lllezione 12 Template ü Il g++ supporta il modello ad inclusione ® istanzia i template in tutti i file in cui sono richiesti ® solo una di queste istanziazioni è utilizzata ü Questo modello di compilazione è inefficiente sia per tempo che per spazio ü Possibile migliorare i tempi di compilazione dicendo al compilatore di non generare tutte queste copie Laboratorio di Algoritmi e Strutture Dati 2001 -02 Modello ad Inclusione in g++ 60 Istanziazione Esplicita in un file è possibile inserire una dichiarazione di istanziazione esplicita ® Istanzia sia la classe che tutti i suoi metodi ü Le definizioni dei metodi devono essere visibili ® ® l’istanziazione esplicita si deve trovare nello stesso file della definizione dei template di funzione In genere si inserisce la definizione del template in un file di implementazione insieme alle istanziazioni esplicite template class Coda<int>; ü Bisogna garantire che il compilatore non istanzi gli stessi metodi anche in altri file ® si usa un opzione di compilazione per dire al compilatore di Laboratorio di Algoritmi e Strutture Dati 2001 -02 ü Per obbligare il compilatore a generare una certa istanza istanziare template solo se il programma ne fa richiesta esplicita ® in g++ Opzione no_implicit_istantiation Laboratorio di Algoritmi e Strutture Dati 2001/02 61 31 Lllezione 12 Template ü La dichiarazione del template viene inclusa in ogni file dove il template è utilizzato. La definizione viene inclusa in un file di implementazione linkato al programma ® ® le istanze del template sono gestite come le funzioni non inline la definizione del template deve essere resa visibile a tutti i file export template <class T> T min(T x, T y) { … } export template <class T> Coda { … }; su molti compilatori questa organizzazione non funziona (Es. g++) Laboratorio di Algoritmi e Strutture Dati 2001 -02 Modello a Separazione 62 file min.h template <class T> T min(T, T); file min.C export template <class T> T min(T a, T b) { return (a < b ? a : b); } #include “min.h” file main.C main() { int i = min(3, 6); } Laboratorio di Algoritmi e Strutture Dati 2001 -02 Esempio 63 Laboratorio di Algoritmi e Strutture Dati 2001/02 32