2017-09-30 2 views
0

j'ai fait deux classes de test:type SFINAE dans VS2015 compile, mais génère l'erreur

class Class1 
{ 
public: 
    Class1(int a) {} 
}; 

class Class2 
{ 
public: 
    Class2() {} 
}; 

Et deux fonctions de modèle en utilisant le type SFINAE de décider lequel utiliser. Le second "échouera" si T n'est pas constructible par défaut.

template<typename T> 
T* CreateInstanceTest(char*[!std::is_default_constructible<T>::value] = 0) { return nullptr; } 

template<typename T> 
T* CreateInstanceTest(char*[std::is_default_constructible<T>::value] = 0) { return new T(); } 

Puis-je faire cela:

Class1* obj1 = CreateInstanceTest<Class1>(); 
Class2* obj2 = CreateInstanceTest<Class2>(); 

qui génère l'erreur « plus d'une instance de fonction surchargée « CreateInstanceTest » correspond à la liste des arguments ».

Cependant, il compile bien et fonctionne comme prévu. obj1 devient null et obj2 est créé correctement.

Pourquoi cela se produit-il? Et y a-t-il un moyen de contourner le problème?

+0

Génère une erreur, mais compile bien? – Zereges

+0

Oui. Le texte devient rouge et je vois une erreur dans la "liste d'erreurs", mais il se construit bien et je peux exécuter le programme. Cela fonctionne aussi comme prévu. – MyNiceDisplayName

+0

utilise 'std :: enable_if_t'. – Jarod42

Répondre

3

Il s'agit d'une erreur Intellisense, pas d'une erreur de construction. Intellisense n'est pas parfait, mais comme une solution de contournement, vous pouvez améliorer le code de déduction:

template<typename T> typename ::std::enable_if_t 
< 
    !::std::is_default_constructible<T>::value 
, T * 
> 
CreateInstanceTest(void) { return nullptr; } 

template<typename T> typename ::std::enable_if_t 
< 
    ::std::is_default_constructible<T>::value 
, T * 
> 
CreateInstanceTest(void) { return new T(); } 
+0

Thank vous, cela ne génère en effet aucune erreur. Il ressemble également à une façon plus agréable de faire ce que je voulais. – MyNiceDisplayName

+0

Existe-t-il une raison d'utiliser ':: std' au lieu de simplement' std'? Je ne pense pas que quelqu'un utilise 'std' comme identifiant. – Zereges

+0

@Zereges En fait, cela arrive parfois. Par exemple, les gens apportent quelque chose dans l'espace de noms 'std' mais gâchent la portée et génèrent l'espace de noms' std' imbriqué au lieu de root. Il est toujours préférable d'être prudent et puisque l'utilisation de "::" ne comporte aucun piège, je l'utilise toujours. – VTT