template - C++ diferentes métodos de plantilla llamados en la misma variable
template tags django (3)
¿Podría alguien explicar por qué una vez se usa el método c(T*)
y la próxima vez d<>(int*)
? Los métodos c
me parecen idénticos y no puedo entender por qué no se llama el mismo tipo de método.
#include <iostream>
using namespace std;
template<typename T>
void c(T){ cout <<"(T)" << endl; }
template<>
void c<>(int*){ cout <<"(int*)" << endl; }
template<typename T>
void c(T*){ cout <<"(T*)" << endl; }
template<typename T>
void d(T){ cout <<"(T)" << endl; }
template<typename T>
void d(T*){ cout <<"(T*)" << endl; }
template<>
void d<>(int*){ cout <<"(int*)" << endl; }
int main(){
int i;
c(&i);
d(&i);
return 0;
}
Salida:
(T*)
(int*)
Acabas de encontrarte con una parte fea de C ++.
El paso de resolución de sobrecarga, durante la compilación, se trata de encontrar la mejor sobrecarga para el código actual. Se ejecuta en un conjunto de funciones y plantillas de funciones que se seleccionaron durante la fase de búsqueda y tiene como objetivo identificar una (y solo una) sobrecarga que sea mejor que otras.
Para las plantillas de función, se segregan en dos grupos:
- Plantillas de función "base"
- plantillas de funciones especializadas
y el proceso de resolución de sobrecargas tiene dos pasos:
- Elija la mejor combinación entre la función normal y las plantillas de función "base"
- Si se selecciona una plantilla de función "base" en el paso 1., elija la mejor especialización (si corresponde, use la "base")
En ambos ejemplos, la mejor función "base" es c(T*)
d(T*)
, por lo que este es el segundo paso que difiere. Por qué ?
Porque, para ser una especialización de una plantilla de función, dicha plantilla de función debe ser declarada primero .
Así:
-
c<>(int*)
es una especialización dec(T)
-
d<>(int*)
es una especialización ded(T*)
y por lo tanto, cuando se selecciona c(T*)
en el paso 1, entonces no hay mejor especialización mientras que cuando se selecciona d(T*)
, d<>(int*)
es una especialización mejor.
Debido a que esto es complicado, la recomendación de los expertos ... NO es usar la especialización de plantillas de función. Simplemente se mezcla extrañamente con la sobrecarga de la plantilla de función.
La resolución de sobrecarga solo selecciona una plantilla base (o una función sin plantilla, si hay una disponible). Solo después de que se haya decidido qué plantilla base se seleccionará, y esa opción se bloquee, el compilador mirará a su alrededor para ver si hay una especialización adecuada de esa plantilla disponible, y si es así, esa especialización se usará.
Para la función c
la especialización void c<>(int*)
es para void c(T)
sobrecarga, mientras que para d
la especialización void d<>(int*)
es void d(T*)
overload.
Entonces, según la explicación anterior, el primer void c(T)
se inspecciona y se ignora sobre la mejor sobrecarga el void c(T*)
(que no tiene especializaciones) que se imprime. Para d
también, la sobrecarga void d(T*)
se bloquea, pero luego se anota la especialización void d(int*)
y luego se elige.
template <typename T>
void c(T); // 1: function template
template <>
void c<>(int*); // 2: specialization of 1
template<typename T>
void c(T*); // 3: overload of 1
template<typename T>
void d(T); // 4: function template
template<typename T>
void d(T*); // 5: overload of 4
template<>
void d<>(int*); // 6: specialization of 5
// ...
int i;
c(&i); // 3 is more appropriate overload than 1
d(&i); // 5 is more appropriate overload than 4
// and it has the suitable specialization 6
Diagrama:
c d
/ / / /
overloads 1 (3) 4 (5) |
| | | priority
specializations 2 (6) V