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
.
No veo ningún tamaño de ... –
@thyrgle: esto tiene la ventaja sobre' sizeof' que , si accidentalmente le da un puntero en lugar de una matriz, no podrá compilar. –
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. –