c++ - template - Argumentos mágicos en plantillas de funciones.
template en c++ pdf (3)
Funciona porque el tipo de a
es "matriz de longitud 6 de int
" y el tipo de b
es "matriz de longitud 1 de int
". El compilador lo sabe, por lo que puede llamar a la función correcta. En particular, la primera llamada llama a la instancia de plantilla cal_size<6>()
y la segunda llama a cal_size<1>()
, ya que esas son las únicas instancias de plantilla que coinciden con sus respectivos argumentos.
Si intentara llamar a una instancia de plantilla explícita, solo funcionaría si tiene el tamaño correcto, de lo contrario los argumentos no coincidirían. Considera lo siguiente:
cal_size(a); // ok, compiler figures out implicitly that N=6
cal_size<int, 6>(a); // also ok, same result as above
cal_size<int, 5>(a); // ERROR: a is not of type "array of length 5 of int"
En el siguiente código
#include<iostream>
template<typename T,size_t N>
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);
}
Como era de esperar, el tamaño de ambas matrices se imprime. Pero, ¿cómo se inicializa N automáticamente en el valor correcto del tamaño de la matriz (las matrices se pasan por referencia)? ¿Cómo funciona el código anterior?
cuando declara int a [] = {1,2,3} es lo mismo que (o se reescribirá como) int a [3] = {1,2,3} ya que la función de plantilla recibe un argumento en forma de T a [N], entonces N tendrá un valor de 3.
N
no se "inicializa" a nada. No es una variable. No es un objeto. N
es una constante en tiempo de compilación. N
solo existe durante la compilación. El valor de N
, así como la T
real, está determinado por el proceso llamado deducción del argumento de la plantilla . Tanto la T
como la N
se deducen del tipo real del argumento que pasa a su función de plantilla.
En la primera llamada, el tipo de argumento es int[6]
, por lo que el compilador deduce que T == int
y N == 6
, genera una función separada para eso y la llama. Llamémoslo cal_size_int_6
void cal_size_int_6(int (&a)[6])
{
std::cout << "size of array is: " << 6 << std::endl;
}
Tenga en cuenta que ya no hay T
ni N
en esta función. Ambos fueron reemplazados por sus valores deducidos reales en el momento de la compilación.
En la primera llamada, el tipo de argumento es int[1]
, por lo que el compilador deduce que T == int
y N == 1
, genera una función separada para eso también y la llama. Llamémoslo cal_size_int_1
void cal_size_int_1(int (&a)[1])
{
std::cout << "size of array is: " << 1 << std::endl;
}
Lo mismo aqui.
Su main
esencialmente se traduce en
int main()
{
int a[]={1,2,3,4,5,6};
int b[]={1};
cal_size_int_6(a);
cal_size_int_1(b);
}
En otras palabras, su plantilla cal_size
da nacimiento a dos funciones diferentes (las llamadas especializaciones de la plantilla original), cada una con diferentes valores de N
(y T
) codificados en el cuerpo. Así es como funcionan las plantillas en C ++.