Vincoli impliciti
Un importante aspetto da tenere presente quando si scrivono e si utilizzano
template (siano essi classi template o, come vedremo, funzioni) e` che la loro
istanziazione possa richiedere che su uno o piu` dei parametri del template
sia definita una qualche funzione o operazione. Esempio:
template < typename T >
class TOrderedList {
public:
/* ... */
T& First(); // Ritorna il primo valore
// della lista
void Add(T& Data);
/* ... */
private:
/* ... */
};
/* Definizione della funzione First() */
template < typename T >
void TOrderedList< T >::Add(T& Data) {
/* ... */
T& Current = First();
while (Data < Current) { // Attenzione qui!
/* ... */
}
/* ... */
}
la funzione Add tenta un confronto tra due valori di tipo T
(parametro del template). La cosa e` perfettamente legale, solo che implicitamente
si assume che sul tipo T sia definito operator < ;
il tentativo di istanziare tale template con un tipo su cui tale operatore non
e` definito e` pero` un errore che puo` essere segnalato solo quando il compilatore
cerca di creare una istanza del template.
Purtroppo il linguaggio segue la via dei vincoli impliciti, ovvero non fornisce
alcun meccanismo per esplicitare assunzioni fatte sui parametri dei template,
tale compito e` lasciato ai messaggi di errore del compilatore e alla buona
volonta` dei programmatori che dovrebbero opportunamente commentare situazioni
di questo genere.
Problemi di questo tipo non ci sarebbero se si ricorresse al polimorfismo, ma
il prezzo sarebbe probabilmente maggiore dei vantaggi.
|