2017-01-04 1 views
2

. J'ai écrit ce code après avoir lu enable_if method specialization. Je veux que la méthode hello() n'existe que si l'argument template est bool et cela fonctionne. Cependant, je rencontre des problèmes lorsque j'essaie de résoudre le même problème en utilisant enable_if. J'ai le code suivant. Toute aide est appréciée. Si enable_if n'est pas approprié pour ce travail, qu'est-ce qui est généralement utilisé?compilation conditionnelle de la méthode de membre d'argument vide en utilisant enable_if

#include <iostream> 
#include <type_traits> 

using namespace std; 

template<typename T> 
struct MyClass{ 

    typename std::enable_if<std::is_same<T,bool>::value, void>::type 
    hello(void) 
    { 
    cout<<"hello only for bools"<<endl; 
    } 
}; 

int main(int argc, char** argv){ 

    MyClass<bool> myclass1; 
    myclass1.hello(); 

    MyClass<float> myclass2;// compilation error. Don't know how to solve 
    //myclass2.hello(); //I want only this line to cause compilation error 

    return 0; 
} 

EDIT: J'ai trouvé la solution à ma question dans la réponse de jpihl à std::enable_if to conditionally compile a member function. Mais pourrait-on expliquer pourquoi ce qui précède ne fonctionne pas?

#include <iostream> 
#include <type_traits> 

using namespace std; 

template<typename T> 
struct MyClass{ 

    template<class Q = T> 
    typename std::enable_if<std::is_same<Q, bool>::value, void>::type hello() 
    { 
    cout<<"hello only for bools"<<endl; 
    } 

}; 

int main(int argc, char** argv){ 

    MyClass<bool> myclass1; 
    myclass1.hello(); 

    MyClass<float> myclass2;// throws errow. Don't know how to solve 
    myclass2.hello(); // 

    return 0; 
} 

Répondre

1

Votre première tentative avec enable_if ne fonctionne pas parce que SFINAE applique dans la résolution de surcharge de la fonction (ou fonction membre) modèles, où il éliminera une spécialisation du modèle de fonction de l'ensemble de surcharge lorsque ce spécialisation ne peut pas compiler.

Le membre hello, lors de votre première tentative, n'est pas une fonction membre modèle. Il n'a aucun paramètre de modèle. C'est simplement un membre fonction d'un modèle classe.

Son type de retour est formulé par une expression enable_if qui provoqueront l'échec de compilation si le paramètre de modèle classe T n'est pas instancié comme bool. Cela ne fait pas fonctionner le membre lui-même dans un modèle. SFINAE n'a pas d'application. Une fois que vous déclarez MyClass<float> myclass2, la spécialisation de MyClass<T> et tous ses membres est complètement déterminée. La fonction membre hello de cette spécialisation doit être être instanciée, et avec T = float la tentative de le faire doit échouer à compiler.

Dans la seconde, tentative réussie, helloest un modèle de fonction membre (de un modèle de classe). Il a un paramètre de modèle, Q, qui est par défaut = T. SFINAE s'applique donc et vous pouvez l'utiliser avec enable_if de la manière prévue. Vous pouvez déclarer MyClass<float> myclass2 sans erreur, car cela ne force pas instanciation de l'élément de modèle MyClass<float>::hello<Q>

Puisque vous avez écrit une seule surcharge de hello, il n'y a qu'une seule spécialisation du modèle de fonction membre pour tout choix de Q. Lorsque Q = bool, cette spécialisation unique survit et myclass1.hello() va compiler . Lorsque Q! = bool, SFINAE élimine la spécialisation unique et myclass2.hello() ne compile pas.

Pour appeciate clairement comment SFINAE dans le second cas fonctionne à instantiation de le modèle de fonction de membre , considérer que:

MyClass<float> myclass2; 
    myclass2.hello<bool>(); 

est bien; tandis que d'autre part:

MyClass<bool> myclass1; 
    myclass1.hello<float>(); 

ne compile pas.

Voici documentation of SFINAE

+0

Cela l'a rendu absolument clair. Merci beaucoup. – user2709349

+1

@ user2709349 Et bienvenue dans Stackoverflow! La façon de dire merci pour une réponse ici est de [accepter la réponse] (http://stackoverflow.com/help/accepted-answer) en cochant la case grise. –