c++ - proyectos - workaround traduccion
¿Qué significa este código C++? (3)
El siguiente código devuelve el tamaño de una matriz asignada a la pila:
template<typename T, int size>
int siz(T (&) [size])
{
return size;
}
Pero no puedo envolver mi cabeza alrededor de la sintaxis. Especialmente la parte T (&) [size]
...
Pero no puedo envolver mi cabeza alrededor de la sintaxis. Especialmente la parte
T (&) [size]
...
Esa parte es una referencia a una matriz. Existe la "regla de derecha-izquierda" para descifrar cualquier declaración de C y C ++.
Como las plantillas de función deducen los tipos de argumentos de la plantilla de los argumentos de función proporcionados, lo que hace esta plantilla de función es deducir el tipo y el recuento de elementos de una matriz y devolver el recuento.
Las funciones no pueden aceptar tipos de matriz por valor, sino solo por puntero o referencia. La referencia se usa para evitar la conversión implícita de una matriz al puntero a su primer elemento (también conocido como caída de matriz):
void foo(int*);
int x[10];
int* p = x; // array decay
foo(x); // array decay again
La desintegración de la matriz destruye el tipo original de la matriz y, por lo tanto, su tamaño se pierde.
Tenga en cuenta que, dado que se trata de una llamada de función en C ++ 03, el valor de retorno no es una constante de tiempo de compilación (es decir, el valor de retorno no se puede usar como un argumento de plantilla). En C ++ 11, la función se puede marcar con constexpr
para devolver una constante de tiempo de compilación:
template<typename T, size_t size>
constexpr size_t siz(T(&)[size]) { return size; }
Para obtener el recuento de elementos del arreglo como una constante de tiempo de compilación en C ++ 03, se puede usar una forma ligeramente diferente:
template<class T, size_t size>
char(&siz(T(&)[size]))[size]; // no definition required
int main()
{
int x[10];
cout << sizeof siz(x) << ''/n'';
double y[sizeof siz(x)]; // use as a compile time constant 10
}
En lo anterior, declara una plantilla de función con el mismo argumento de referencia a una matriz, pero con el tipo de valor de retorno de char(&)[size]
(aquí es donde se puede apreciar la "regla derecha-izquierda"). Tenga en cuenta que la llamada a la función nunca ocurre en tiempo de ejecución, es por esto que la definición del siz
plantilla de la función es innecesaria. sizeof siz(x)
básicamente dice "cuál sería el tamaño del valor de retorno si se llamara siz(x)
" .
La antigua forma C / C ++ de obtener el recuento de elementos de una matriz como una constante de tiempo de compilación es:
#define SIZ(arr) (sizeof(arr) / sizeof(*(arr)))
Es una función que se convierte en un nombre de tipo (las plantillas se pueden usar con diferentes nombres de tipo) y un tamaño desde el exterior. A continuación, devuelve este tamaño.
Las funciones de pila a menudo utilizan size
, que es un número entero que le muestra el tamaño del tamaño de pila que solicita con esta función. El &
prueba solo a qué tamaño de pila T se refiere.
T (&) [size]
es una referencia a una matriz. Debe ser una referencia porque el siguiente programa no es legal:
#include <iostream>
int sz(int *) { std::cout << "wtf?" << std::endl; return 0; }
int sz(int [4]) { std::cout << "4" << std::endl; return 0; }
int main() {
int test[4];
sz(test);
}
Este programa no se compila con:
test.cc: In function ‘int sz(int*)’:
test.cc:6:5: error: redefinition of ‘int sz(int*)’
test.cc:3:5: error: ‘int sz(int*)’ previously defined here
porque int sz(int [4])
es idéntico a int sz(int *)
.
Se requiere que los paréntesis se desambiguen aquí porque T& [size]
parece una matriz de referencias que de otra manera es ilegal.
Normalmente, si el parámetro no fuera anónimo, escribirías:
template<typename T, int size>
int sz(T (&arr) [size])
Para darle a la matriz el nombre arr
. En este caso, a pesar de que todo el código de su ejemplo era el tamaño deducido y, por lo tanto, el argumento anónimo evita las advertencias sobre los argumentos no utilizados.