Specifiche dei modelli
La dichiarazione template specifica un insieme di classi o funzioni parametrizzate.
template < template-parameter-list > declaration
Note
Il template-parameter-list è una lista di parametri di template separati da virgola, che possono essere tipi (nella forma class identifier, typename identifier, o template < template-parameter-list > class identifier) o non-tipi da usare nel corpo del template. Di seguito è riportata la sintassi per un parametro.
parameter-declaration
class identifier [ = typename ]
typename identifier [ = typename ]
template < template-parameter-list > class [identifier][= name]
Si può istanziare una classe template come una normale classe, ma si devono includere gli argomenti del template all'interno di parentesi angolate (<>). Gli argomenti del template possono essere di qualsiasi tipo se la lista degli argomenti del template contiene la classe o la parola chiave typename, o un valore del tipo appropriato se l'argomento è un non-tipo. Non è richiesta nessuna sintassi particolare per chiamare una funzione template, sebbene possono essere richieste le parentesi angolate e gli argomenti del template se i parametri del template non possono essere dedotti degli argomenti della funzione.
Il template-parameter-list è una lista di parametri usata dalla funzione template che specifica quali parti del codice a seguire possono variare. Ad esempio:
template< class T, int i > class MyStack...
In questo caso, il template può ricevere un type (class T) and un parametro costante (int i). Una volta istanziato, il modello userà il tipo T ed il parametro costante intero i. Dentro il corpo della dichiarazione MyStack, si può fare riferimento all'identificatore T.
Una dichiarazione di template da sé non genera alcun codice; essa specifica una famiglia di classi o funzioni, una o più, che saranno generate quando referenziate da un altro codice sorgente.
Le dichiarazioni di template hanno visibilità globale, all'interno del namespace o della classe. Non possono essere dichiarate dentro una funzione.
Il seguente esempio mostra la dichiarazione, definizione e istanziazione di una classe template con un parametro tipato T e un parametro template non tipato i.
// template_specifications1.cpp
template <class T, int i> class TestClass
{
public:
char buffer[i];
T testFunc(T* p1 );
};
template <class T, int i>
T TestClass<T,i>::testFunc(T* p1)
{
return *(p1++)
};
// To create an instance of TestClass
TestClass<char, 5> ClassInst;
int main()
{
}
argomenti del template non tipati
Argomenti non tipati del template devono essere del tipo intero, enumerazione, referenza o puntatore ad un tipo membro, e devono essere costanti a compile time. Possono essere qualificati come tipi const o volatile. Valori in virgola mobile non sono ammessi come parametri del template. Oggetti di tipo classe, struct o union non sono ammessi come parametri di template non tipati, sebbene sono ammessi puntatori a tali oggetti. Array passati come parametri non tipati vengono convertiti in puntatori. Funzioni passati come parametri non tipati vengono convertiti in puntatori a funzione. Le stringhe non sono ammesse come parametri del template.
Usando typename in una dichiarazione di template
È possibile utilizzare la parola chiave typename nella lista dei parametri del template. Le seguenti dichiarazioni di template sono identiche:
template< class T1, class T2 > class X...
template< typename T1, typename T2 > class X...
Argomenti di default per i parametri di un template
Classi template possono avere argomenti di default specificati usando il simbolo = seguito dal tipo o dal valore di default. Le funzioni template non possono avere argomenti di default. Per ulteriori informazioni, vedere Argomenti predefiniti per modelli di classe.:
template<typename Type> class allocator {};
template<typename Type,
typename Allocator = allocator<Type> > class stack
{
};
stack<int> MyStack;
Riutilizzo dei parametri template
I parametri del template possono essere riusati nella lista dei parametri del template Per esempio, il seguente codice è ammesso:
// template_specifications2.cpp
class Y
{
};
template<class T, T* pT> class X1
{
};
template<class T1, class T2 = T1> class X2
{
};
Y aY;
X1<Y, &aY> x1;
X2<int> x2;
int main()
{
}
I template come parametri del template
I parametri del template possono essere essi stessi dei template. Questo costrutto significa che l'argomento deve esso stesso essere un template, non una classe costruita dal template. Nel seguente esempio, il nome A del parametro del template può essere omesso, perché esso non può essere usato.
// template_specifications3.cpp
#include <stdio.h>
template <class T> struct str1
{
T t;
};
template <template<class A> class T> struct str2
{
T<int> t;
};
int main()
{
str2<str1> mystr2;
mystr2.t.t = 5;
printf_s("%d\n", mystr2.t.t);
}
Output
5
Reference come parametri del template.
Visual Studio .NET 2003 introduce la possibilità di usare le reference come parametri di template non tipati. Questo non era ammesso nelle versioni precedenti.
// references__supported_as_nontype_template_parameters.cpp
#include <stdio.h>
extern "C" int printf_s(const char*,...);
template <int & ri> struct S
{
S()
{
printf_s("ri is %d\n", ri);
}
~S()
{
printf_s("ri is %d\n", ri);
}
};
int i = 1;
int main()
{
S<i> s;
i = 0;
}
Output
ri is 1
ri is 0
Istanze annidate di template
Versioni di Visual Studio precedenti a Visual Studio 2005 richiedono che debbano essere inseriti degli spazi tra la lista dei parametri del template quando vengono dichiarate istanze annidate di template. LE seguente sintassi non è ammessa:
// template_specifications4.cpp
template <typename T>
class A
{
};
template <int n>
class B
{
};
int main()
{
A<B<22>>();
}