Notez qu'il ya sont extrait de code qui sont valides pour les deux le mot-clé ajouté et pas ajouté, ce qui donne des résultats différents dans chaque cas, même pour les modèles qui prennent des paramètres de type au lieu d'entiers.
#include <iostream>
struct A {
template<typename T>
static A f(T) {
return A();
}
template<typename T> operator T() { return T(); }
};
template<typename U>
int g() {
U u;
typedef A (*funcPtrType)(int());
return !(funcPtrType)u.f < int() > (0);
}
int main() {
std::cout << g<A>() << std::endl;
}
Ce sorties 0
lorsqu'il est exécuté sans le mot-clé template
ajouté. Si vous ajoutez le mot-clé avant f < int() >
, il sort 1
.
Explication
La version sans le mot-clé parse comme
funcPtrType temp1 = (funcPtrType)u.f; // taking func address
bool temp2 = !temp1; // temp2 == false
bool temp3 = temp2 < int(); // temp3 == false
bool temp4 = temp3 > (0); // temp4 == false
return temp4;
Et la version avec le mot-clé parse comme
A temp1 = u.template f < int() > (0); // function call
funcPtrType temp2 = (funcPtrType) temp1; // temp2 == 0
bool temp3 = !temp2; // temp3 == true
return temp3;
Notez que temp2
est un pointeur NULL (produit par return T()
). Des analyses différentes entières, et les deux sont valides! Cela a vraiment besoin d'un moyen de désambiguïsation - qui est d'insérer le mot-clé template
le cas échéant.