Argomenti magici nei modelli di funzioni

Nel seguente codice

#include template void cal_size(T (&a)[N]) { std::cout<<"size of array is: "<<N<<std::endl; } int main() { int a[]={1,2,3,4,5,6}; int b[]={1}; cal_size(a); cal_size(b); } 

Come previsto, la dimensione di entrambi gli array viene stampata. Ma come viene automaticamente inizializzato N sul valore corretto della dimensione dell’array (gli array vengono passati per riferimento)? Come funziona il codice sopra?

N non viene “inizializzato” a nulla. Non è una variabile. Non è un object. N è una costante in fase di compilazione. N esiste solo durante la compilazione. Il valore di N e l’effettiva T sono determinati dal processo chiamato deduzione argomento template . Sia T che N sono dedotte dal tipo effettivo dell’argomento passato alla funzione template.

Nella prima chiamata l’argomento type è int[6] , quindi il compilatore deduce che T == int e N == 6 , genera una funzione separata per quello e la chiama. Diamo il nome cal_size_int_6

 void cal_size_int_6(int (&a)[6]) { std::cout << "size of array is: " << 6 << std::endl; } 

Nota che non ci sono più né TN in questa funzione. Entrambi sono stati sostituiti dai loro reali valori dedotti al momento della compilazione.

Nella prima chiamata l'argomento type è int[1] , quindi il compilatore deduce che T == int e N == 1 , genera una funzione separata anche per quello e la chiama. Diamo il nome cal_size_int_1

 void cal_size_int_1(int (&a)[1]) { std::cout << "size of array is: " << 1 << std::endl; } 

La stessa cosa qui.

Il tuo main traduce essenzialmente in

 int main() { int a[]={1,2,3,4,5,6}; int b[]={1}; cal_size_int_6(a); cal_size_int_1(b); } 

In altre parole, il tuo modello cal_size dà vita a due diverse funzioni (le cosiddette specializzazioni del modello originale), ognuna con diversi valori di N (e T ) hardcoded nel corpo. Ecco come i template funzionano in C ++.

Funziona perché il tipo di a è “array di lunghezza 6 di int ” e il tipo di b è “array di lunghezza 1 di int “. Il compilatore lo sa, quindi può chiamare la funzione corretta. In particolare, la prima chiamata chiama l’istanza modello cal_size<6>() e la seconda chiamata chiama cal_size<1>() , poiché queste sono le uniche istanze di modello che corrispondono ai rispettivi argomenti.

Se si è tentato di chiamare un’istanza di modello esplicita, funzionerà solo se si ottiene la dimensione giusta, altrimenti gli argomenti non corrisponderanno. Considera quanto segue:

 cal_size(a); // ok, compiler figures out implicitly that N=6 cal_size(a); // also ok, same result as above cal_size(a); // ERROR: a is not of type "array of length 5 of int" 

quando dichiari int a [] = {1,2,3} è uguale a (o verrà riscritto come) int a [3] = {1,2,3} poiché la funzione basata su modello sta ricevendo argomento in forma di T a [N], quindi N avrà valore di 3.