Cosa significa template ?

Quando dichiaro un modello, sono abituato ad avere questo tipo di codice:

template  

Ma in questa domanda , hanno usato:

 template  

Ho controllato che si compili. Ma cosa significa? È un parametro non di tipo? E se sì, come possiamo avere un modello senza alcun parametro di tipo?

È perfettamente ansible modellare una class su un intero piuttosto che su un tipo. Possiamo assegnare il valore di modello a una variabile, o altrimenti manipolarlo in un modo che potremmo con qualsiasi altro intero letterale:

 unsigned int x = N; 

In effetti, possiamo creare algoritmi che valutano in fase di compilazione (da Wikipedia ):

 template  struct Factorial { enum { value = N * Factorial::value }; }; template <> struct Factorial<0> { enum { value = 1 }; }; // Factorial<4>::value == 24 // Factorial<0>::value == 1 void foo() { int x = Factorial<4>::value; // == 24 int y = Factorial<0>::value; // == 1 } 

Sì, è un parametro non di tipo. Puoi avere diversi tipi di parametri del modello

  • Digitare i parametri.
    • tipi
    • Modelli (solo modelli di classi e alias, senza funzioni o modelli variabili)
  • Parametri non di tipo
    • puntatori
    • Riferimenti
    • Espressioni costanti integrali

Quello che hai lì è dell’ultimo tipo. È una costante di tempo di compilazione (la cosiddetta espressione costante) ed è di tipo intero o enumerazione. Dopo averlo esaminato nello standard, ho dovuto spostare i modelli di class nella sezione dei tipi, anche se i modelli non sono tipi. Ma sono chiamati parametri di tipo allo scopo di descriverli comunque. È ansible avere puntatori (e anche puntatori membri) e riferimenti a oggetti / funzioni che hanno un collegamento esterno (quelli che possono essere collegati da altri file object e il cui indirizzo è univoco nell’intero programma). Esempi:

Parametro tipo di modello:

 template struct Container { T t; }; // pass type "long" as argument. Container test; 

Parametro intero modello:

 template struct Vector { unsigned char bytes[S]; }; // pass 3 as argument. Vector<3> test; 

Parametro del puntatore del modello (passando un puntatore a una funzione)

 template struct FunctionWrapper { static void call_it() { F(); } }; // pass address of function do_it as argument. void do_it() { } FunctionWrapper<&do_it> test; 

Parametro di riferimento del modello (passando un intero)

 template struct SillyExample { static void do_it() { A = 10; } }; // pass flag as argument int flag; SillyExample test; 

Parametro del modello di modello.

 template class AllocatePolicy> struct Pool { void allocate(size_t n) { int *p = AllocatePolicy::allocate(n); } }; // pass the template "allocator" as argument. template struct allocator { static T * allocate(size_t n) { return 0; } }; Pool test; 

Un modello senza parametri non è ansible. Ma un modello senza argomenti espliciti è ansible – ha argomenti predefiniti:

 template struct Vector { unsigned char buffer[SIZE]; }; Vector<> test; 

Sintatticamente, il template<> è riservato per contrassegnare una specializzazione modello esplicita, anziché un modello senza parametri:

 template<> struct Vector<3> { // alternative definition for SIZE == 3 }; 

Templatizzi la tua class sulla base di un ‘int unsigned’.

Esempio:

 template  class MyArray { public: private: double data[N]; // Use N as the size of the array }; int main() { MyArray<2> a1; MyArray<2> a2; MyArray<4> b1; a1 = a2; // OK The arrays are the same size. a1 = b1; // FAIL because the size of the array is part of the // template and thus the type, a1 and b1 are different types. // Thus this is a COMPILE time failure. } 

Una class template è come una macro, solo molto meno male.

Pensa a un modello come a una macro. I parametri del modello vengono sostituiti in una definizione di class (o funzione), quando si definisce una class (o funzione) utilizzando un modello.

La differenza è che i parametri hanno “tipi” e i valori passati vengono controllati durante la compilazione, come i parametri delle funzioni. I tipi validi sono i tuoi normali tipi di C ++, come int e char. Quando si crea un’istanza di una class template, si passa un valore del tipo specificato e in una nuova copia della definizione della class template questo valore viene sostituito ovunque il nome del parametro si trovasse nella definizione originale. Proprio come una macro.

Puoi anche usare i tipi ” class ” o ” typename ” per i parametri (sono davvero gli stessi). Con un parametro di uno di questi tipi, è ansible passare un nome di tipo anziché un valore. Proprio come prima, ovunque il nome del parametro era nella definizione della class del template, non appena si crea una nuova istanza, diventa qualsiasi tipo si passi. Questo è l’uso più comune per una class template; Tutti quelli che sanno qualcosa sui modelli C ++ sanno come farlo.

Considera questo codice di esempio di class template:

 #include  template  class foo { void print() { printf("%i", I); } }; int main() { foo<26> f; f.print(); return 0; } 

Funzionalmente è uguale a questo codice che utilizza la macro:

 #include  #define MAKE_A_FOO(I) class foo_##I \ { \ void print() \ { \ printf("%i", I); \ } \ }; MAKE_A_FOO(26) int main() { foo_26 f; f.print(); return 0; } 

Naturalmente, la versione del modello è un miliardo di volte più sicura e più flessibile.