2010-07-30 8 views
40

duplicados posibles:
Can someone explain this template code that gives me the size of an array?
Magic arguments in function templates…¿Cómo funciona esta plantilla de "tamaño de matriz"?

Puede alguien explicar cómo funciona este código? Yo sé que el propósito de este código es para obtener la longitud de una matriz, pero no sé cómo funciona este código:

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

Gracias.

+0

No veo ningún tamaño de ... –

+5

@thyrgle: esto tiene la ventaja sobre' sizeof' que , si accidentalmente le da un puntero en lugar de una matriz, no podrá compilar. –

+1

Otro duplicado más. ASÍ QUE realmente tiene un problema con todos los engañados http://stackoverflow.com/questions/437150/can-someone- explique-este-plantilla-código-que-me-da-el-tamaño-de-un-array (hay un par de otros engañados para esto). Me pregunto si soy el único que los encuentra y los marca. Con 4 votos requeridos, estos engañados apenas se cierran, como he encontrado en otras preguntas que marqué de esa manera. Los votos de personas con mayor reputación deberían contar más que los votos de otras personas. De esta forma, las preguntas se pueden cerrar más rápido. –

Respuesta

50

Analicemos primero el parámetro, T(&)[size]. Leer declaraciones de adentro hacia afuera, de derecha a izquierda, primero el grupo de paréntesis: es un parámetro sin nombre que hace referencia a una matriz de tamaño size del tipo T.

Es decir, acepta una referencia a cualquier matriz, donde el tipo y el tamaño de la matriz son parámetros de plantilla.

Si lo llamamos como tal:

int a[10]; 
GetArrLength(a); 

El compilador tratará de deducir los parámetros de plantilla. Para que el tipo de parámetro coincida con lo que está pasando, T debe ser int y size debe ser 10 (haciendo que el parámetro sea una referencia a una matriz de 10 int s).

Luego devuelve ese tamaño, proporcionándole la cantidad de elementos en una matriz.


Existen dos "problemas" con este código. En primer lugar, los tamaños no pueden ser negativos, por lo que no tiene sentido utilizar un tipo con signo como parámetro de plantilla y tipo de retorno. Por el contrario, se debe utilizar un tipo sin signo; mejor sería std::size_t:

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

La segunda es que el resultado de esta función no es una constante, expresión, a pesar de que el tamaño de un array es. Si bien eso está bien en la mayoría de las situaciones, sería mejor si pudiéramos obtener una expresión constante de ello. Ahí es donde se termina con esta solución:

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)) 

Esto se utiliza como tal:

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

Funciona por tres cosas: la primera es la misma idea que el anterior, se llenarán que los parámetros de plantilla dándote el tamaño de la matriz.

La segunda parte está utilizando esa información para hacer un tipo con un tamaño específico, de ahí el ayudante type_of_size. Esa parte no es estrictamente necesaria, pero creo que hace que el código sea más fácil de leer. A char[N] tiene un tamaño igual a N, siempre, por lo tanto podemos abusar de eso para "almacenar" el tamaño de la matriz ... en el tamaño de un tipo sí mismo!

La tercera parte obtiene ese tamaño con sizeof. En realidad, no evalúa nada, por lo que no necesitamos una definición para la función. Simplemente dice "Si fueras a hacer esto ...el tamaño sería ... ". Y el tamaño es nuestro tamaño" almacenado ", en la matriz char.

+0

pero si cambio el código a T y [tamaño] no funcionará, ¿por qué? cuál es la diferencia entre (&) y solamente & gracias – BobAlmond

+5

T & [size] es una serie de referencias. Desea una referencia a una matriz. –

+0

@Bob: Tiene que ver con las declaraciones. Puede que te confundas porque no tiene nombre, intenta meter uno allí. Con 'T (& x) [N]' x es referencia a una matriz de N T's. Pero con: 'T & x [N]' x es una matriz de N referencias a T. (que es ilegal.) Leer las declaraciones de adentro hacia afuera, de derecha a izquierda, paréntesis primero. – GManNickG

Cuestiones relacionadas