2010-07-30 13 views
40

Possibili duplicati:
Can someone explain this template code that gives me the size of an array?
Magic arguments in function templates…Come funziona questa funzione di template "size of array"?

qualcuno può spiegare come funziona questo codice? So che lo scopo di questo codice è quello di ottenere la lunghezza di un array, ma non so come funziona questo codice:

template<typename T, int size> 
int GetArrLength(T(&)[size]){return size;} 

Grazie.

+0

Non vedo alcuna dimensione di ... –

+5

@thyrgle: questo ha il vantaggio su' sizeof' che , se accidentalmente gli dai un puntatore invece di un array, non riuscirà a compilarlo –

+1

Ancora un altro duplicato, quindi ha davvero un problema con tutti i duplicati. http://stackoverflow.com/questions/437150/can-someone- spiegare-questo-modello-codice-che-dà-me-la-dimensione-di-un-array (ci sono un paio di altri duplicati per questo). Mi chiedo se sono l'unico che trova e segna questi. Con 4 voti richiesti, questi capricci sono appena chiusi, come ho trovato in altre domande che ho contrassegnato in questo modo.Le opinioni di persone con una reputazione più alta dovrebbero contare più dei voti di altre persone.Questo modo, le domande possono essere chiuse più velocemente –

risposta

50

Prima di analizzare il parametro, T(&)[size]. Leggi le dichiarazioni dall'interno verso l'esterno, da destra a sinistra, prima il gruppo di parentesi: è un parametro senza nome che è un riferimento a un array di dimensioni size di tipo T.

Cioè, accetta un riferimento a qualsiasi array, in cui il tipo e la dimensione dell'array sono parametri del modello.

Se lo chiamiamo come tale:

int a[10]; 
GetArrLength(a); 

Il compilatore cercherà di dedurre i parametri del modello. Affinché il tipo di parametro corrisponda a quello che stai passando, T deve essere int e size deve essere 10 (rendendo il parametro un riferimento a un array di 10 int s).

Quindi si restituisce quella dimensione, fornendo il numero di elementi in una matrice.


Ci sono due "problemi" con questo codice. Innanzitutto, le dimensioni non possono essere negative, quindi non ha senso utilizzare un tipo firmato come parametro template e tipo restituito. Piuttosto, dovrebbe essere usato un tipo senza segno; meglio sarebbe std::size_t:

template<typename T, std::size_t Size> 
std::size_t GetArrLength(T(&)[Size]) { return size; } 

La seconda è che il risultato di questa funzione non è una costante espressione, anche se la dimensione di un array è. Mentre va bene nella maggior parte delle situazioni, sarebbe meglio se potessimo ottenere un'espressione costante da esso. Ecco dove si finisce con questa soluzione:

template <std::size_t N> 
struct type_of_size 
{ 
    typedef char type[N]; 
}; 

template <typename T, std::size_t Size> 
typename type_of_size<Size>::type& sizeof_array_helper(T(&)[Size]); 

#define sizeof_array(pArray) sizeof(sizeof_array_helper(pArray)) 

Questo è usato come tale:

int a[10]; 
const std::size_t n = sizeof_array(a); // constant-expression! 

Funziona da tre cose: la prima è la stessa idea di cui sopra, saranno riempiti che i parametri del modello fuori dando la dimensione della matrice.

La seconda parte utilizza tali informazioni per creare un tipo con una dimensione specifica, da cui l'helper type_of_size. Questa parte non è strettamente necessaria, ma penso che faciliti la lettura del codice. A char[N] ha una dimensione pari a N, sempre, quindi possiamo abusare di questo per "memorizzare" la dimensione della matrice ... nella dimensione di un tipo stesso!

La terza parte sta ottenendo quella dimensione con sizeof. In realtà non valuta nulla, quindi non abbiamo bisogno di una definizione per la funzione. Dice semplicemente "Se dovessi fare questo ...la dimensione sarebbe ... ". E la dimensione è la nostra dimensione" memorizzata ", nell'array char.

+0

ma se cambio il codice in T & [size] non funzionerà, perché? qual è la differenza tra (&) e solo & grazie – BobAlmond

+5

T & [size] è una matrice di riferimenti. Vuoi un riferimento a un array. –

+0

@Bob: ha a che fare con le dichiarazioni. Potresti sentirti confuso perché non c'è un nome per questo, prova a inserirne uno. Con 'T (& x) [N]' x è riferimento a una matrice di N T. Ma con: 'T & x [N]' x è una matrice di N riferimenti a T. (Che è illegale.) Leggi le dichiarazioni da dentro-fuori, da destra a sinistra, prima la parentesi. – GManNickG

Problemi correlati