Sélectionnez le constructeur de classe à l’aide de enable_if

Considérez le code suivant:

#include  #include  template  struct A { int val = 0; template <class = typename std::enable_if::type> A(int n) : val(n) {}; A(...) { } /* ... */ }; struct YES { constexpr static bool value = true; }; struct NO { constexpr static bool value = false; }; int main() { A y(10); A n; std::cout << "YES: " << y.val << std::endl << "NO: " << n.val << std::endl; } 

Je veux définir de manière sélective le constructeur A :: A (int) uniquement pour certains types utilisant enable_if. Pour tous les autres types, il y a le constructeur par défaut A :: A (…) qui devrait être le cas par défaut pour le compilateur en cas d’échec de la substitution. Cependant, cela a du sens pour moi, le compilateur (gcc version 4.9.0 20130714) se plaint toujours

sfinae.cpp: En instanciation de ‘struct A’: sfinae.cpp: 19: 11:
requirejs à partir d’ici sfinae.cpp: 9: 5: erreur: aucun type nommé ‘type’ dans
‘struct std :: enable_if’
A (int n): val (n) {};

Est-ce que quelque chose comme cela est possible pour le constructeur? Est-ce possible avec un autre constructeur (constructeur de copie et constructeur de déplacement)?

Je pense que cela ne peut pas fonctionner avec un seul paramètre de modèle par défaut, car sa valeur doit être résolue lorsque le modèle de classe est instancié.

Nous devons reporter la substitution au point d’instanciation du modèle constructeur. L’une des méthodes consiste à définir le paramètre template sur T et à append un paramètre factice supplémentaire au constructeur:

 template A(int n, typename std::enable_if::type* = 0) : val(n) { } 

Cela se fait généralement en utilisant un argument anonyme par défaut:

 A(int n, typename std::enable_if::type* = 0) : val(n) {}; 

Vous ne pouvez pas utiliser les parameters de modèle de la classe aux méthodes de sortie SFINAE. Donc, une manière consiste à append un type factice en remplaçant int:

voir: http://ideone.com/2Gnyzj

 #include  #include  template  struct A { int val = 0; template::type > A(Integer n) : val(n) {}; A(...) {} /* ... */ }; struct YES { constexpr static bool value = true; }; struct NO { constexpr static bool value = false; }; int main() { A y(10); A n; std::cout << "YES: " << y.val << std::endl << "NO: " << n.val << std::endl; } 

Cela fonctionne parce que vous utilisez un paramètre de modèle de membre pour SFINAE sur le constructeur, mais le test est toujours vrai pour ne pas polluer vos contrôles