Maison >développement back-end >C++ >Pourquoi SFINAE échoue-t-il avec les fonctions membres dans les modèles de classe ?
Fonction membre SFINAE dans les modèles de classe : une explication détaillée
Dans le monde du C, SFINAE (Substitution Failure Is Not An Error) permet optimisations des modèles en évitant les erreurs d'instanciation lors de la compilation. Cependant, lorsqu'il s'agit de fonctions membres de modèles de classe, SFINAE peut se comporter de manière inattendue.
Le problème avec la fonction membre SFINAE
Considérez le code suivant :
<code class="cpp">template <typename T> struct Foo { typename std::enable_if<std::is_same<T, A>::value>::type bar(); typename std::enable_if<std::is_same<T, B>::value>::type bar(); };</code>
Contrairement aux attentes, ce code entraîne un message d'erreur. SFINAE ne fonctionne pas comme prévu pour les fonctions membres au sein d'un modèle de classe.
SFINAE et arguments de modèle déduits
Le nœud du problème réside dans la dépendance de SFINAE à l'égard des arguments de modèle déduits. . Cela ne fonctionne que lorsque l'argument du modèle est déduit de l'appel de fonction. Dans le cas des fonctions membres, les arguments de modèle ne sont pas déduits et sont fournis explicitement.
Une solution utilisant des arguments déduits
Pour résoudre le problème, nous pouvons modifier le codez comme suit :
<code class="cpp">template<typename T> struct Foo { template<typename U = T> typename std::enable_if<std::is_same<U,A>::value>::type bar() { } template<typename U = T> typename std::enable_if<std::is_same<U,B>::value>::type bar() { } };</code>
Maintenant, lors de l'appel de Foo()(x), le compilateur déduit l'argument du modèle T et sélectionne la surcharge correcte en fonction de x. Cette approche permet à SFINAE de fonctionner comme prévu.
Alternative : spécialisation explicite des modèles de classe
Si la structure de la classe est cruciale et ne peut être modifiée, une solution alternative implique spécialisation explicite du modèle de classe :
<code class="cpp">template <typename> struct Foo; template <> struct Foo<A> { void bar() {} }; template <> struct Foo<B> { void bar() {} };</code>
Ici, le compilateur sait exactement quelle spécialisation instancier en fonction du type fourni. Il ne s'appuie pas sur SFINAE pour la sélection des spécialisations.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!