2017-07-14 3 views
1

Je suis nouveau à SFINAE. J'ai remarqué que:déduction de modèle avec SFINAE en C++

template <typename T> void f(T t) { t.Crash(); } // version 1 
void f(...) { } // The sink. 
f(1); 

template <typename T> void f(const T& t, typename T::iterator* it = nullptr) { } // version 2 
void f(...) { } // The sink. 
f(1); 

dans la version 2, en raison de SFINAE, il ne jetterons aucune erreur, et choisissez l'évier d'ellipse. mais pourquoi à la version 1, le compilateur s'arrêtera et se plaindra?

Est-ce que la SFINAE s'applique uniquement à la signature et non au corps? donc dans la version 1, il préfère la fonction template, mais à quelle étape le compilateur s'arrête-t-il et lance-t-il une erreur?

veuillez expliquer explicitement les étapes de traitement du compilateur concernant la résolution de surcharge de modèle.

Répondre

4

mais pourquoi à la version 1, le compilateur va s'arrêter et se plaindre?

template <typename T> void f(T t) { t.Crash(); } // version 1 
void f(...) { } // The sink. 
f(1); 

Il n'y a pas d'échec de substitution là, dans la version de f ci-dessus basé sur un modèle, parce que T peut être déduit que int de l'appel f(1). Et selon les règles de résolution de surcharge, le f<int>(int) est plus préférions que f(...)


template <typename T> void f(const T& t, typename T::iterator* it = nullptr) { } // version 2 
void f(...) { } // The sink. 
f(1); 

Il y a un échec de substitution là, parce que, le compilateur devra déduire le type de it après déduisant T comme int. Il remplace int à la place de int::iterator qui n'est pas valide.


SFINAE sur les fonctions fonctionne dans le cadre de la création d'une spécialisation valide fonction modèle.

Est-ce que la SFINAE s'applique uniquement à la signature et non au corps?

Vous pouvez dire quelque chose comme ça ... Prenez un butin à ces exemples de code valides:

//Just the declaration 
template <typename T> 
void f(T t); 

void f(...); 

int main(){ 
    f(1); //selects f<int>(int) 
} 

Pendant ce temps:

//just the declarations. 
template <typename T> 
void f(const T& t, typename T::iterator* it = nullptr); 

void f(...); 

int main(){ 
    f(1); //selects f(...) 
}