Condividi tramite


Cenni preliminari sui modelli

I modelli, talvolta denominati tipi con parametri, sono meccanismi per la generazione di funzioni e di classi basate sui parametri di tipo. Utilizzando i modelli, è possibile progettare una singola classe o funzione in grado di agire su molti tipi di dati, anziché creare una classe separata per ogni tipo.

Osservazioni

Ad esempio, per creare una funzione indipendente dai tipi che restituisce come minimo due parametri senza utilizzare i modelli, sarebbe necessario scrivere un set di funzioni in overload come il seguente:

// what_are_templates1.cpp
// compile with: /c
// min for ints
int min( int a, int b ) {
   return ( a < b ) ? a : b;
}

// min for longs
long min( long a, long b ) {
   return ( a < b ) ? a : b;
}

// min for chars
char min( char a, char b ) {
   return ( a < b ) ? a : b;
}

Utilizzando i modelli, è possibile sostituire le duplicazioni con un singolo modello di funzione:

// what_are_templates2.cpp
// compile with: /c
template <class T> T min( T a, T b ) {
   return ( a < b ) ? a : b;
}

I modelli possono ridurre notevolmente le dimensioni e aumentare la flessibilità del codice sorgente senza ridurre l'indipendenza dai tipi.

Esistono due tipi principali di modelli: modelli di funzione e modelli di classe. Nell'esempio precedente, min è un modello di funzione. Un modello di classe è una classe con un parametro, ad esempio:

// what_are_templates3.cpp
template <class T> class A {
   T m_t;
   public:
      A(T t): m_t(t) {} 
      void f(T t);
};

int main() {
   A<int> a(10);
}

I modelli vengono dichiarati e definiti più o meno come le altre funzioni e classi, ma con alcune importanti differenze. Una dichiarazione di modello non definisce completamente una funzione o una classe, ma definisce una struttura sintattica per una classe o per una funzione. Le funzioni e le classi vere e proprie vengono create a partire da un modello, attraverso un processo denominato creazione di istanza. Si fa riferimento a tale processo per ogni singola classe o funzione creata. Ad esempio, un modello di classe:

template <class T> struct A { . . . };

può essere utilizzato per creare istanze di classi per A<int>, A<char>, A<int*>, A<MyClass*> e così via.

La creazione di istanze di classi o funzioni può essere eseguita in modo esplicito o implicito. La creazione di istanze esplicita è un modo per indicare nel codice la versione del modello da generare. La creazione di istanze implicita permette di creare istanze di modelli al bisogno e nel punto in cui vengono utilizzate per la prima volta.

I modelli possono anche essere dotati di parametri attraverso un parametro di valore, nel qual caso il parametro di modello viene dichiarato come un parametro a una funzione. Non è consentito utilizzare i tipi a virgola mobile e i tipi di classe come parametri di valore.

// what_are_templates4.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;

template <int i> class A {
   int array[i];
public:
   A() { memset(array, 0, i*sizeof(int)); }
};

int main() {
   A<10> a;
}

Un problema comune dei modelli è che hanno un formato unico per tutti i tipi, ai quali viene quindi applicato lo stesso codice. Se è necessario adeguare il comportamento del modello ad un tipo particolare, è possibile utilizzare la specializzazione. Con la specializzazione esplicita, un modello può essere specializzato per un tipo reale specifico, non per un tipo generico. Il modello di classe può essere specializzato anche parzialmente, il che è utile se si dispone di un modello con più parametri di tipo ed è necessario adeguarne il comportamento solo rispetto ad alcuni parametri, non a tutti. La specializzazione parziale rimane generica e necessita di argomenti di modello reali per produrre un'istanza di classe effettiva.

Vedere anche

Altre risorse

Modelli