Le SFINAE est un outil qui sert à détecter des informations non triviales ou des possibilités par essai et erreur. Sauf que les erreurs sont ignorées et à la place on se débrouille pour récupérer un truc que l'on va assimiler à faux. Ce booléen on s'en sert ensuite ailleurs pour choisir quelle spécialisation nous intéresse.
Exemple à la C++98
template<typenameT>structhas_typedef_montype{usingyes=char[1];usingno=char[2];// Signatures qui renvoient des choses différentes// - Version qui prend ce que l'on cherchetemplate<typenameC>staticyes&test(typenameC::montype*);// - Version qui prend n'importe quitemplate<typenameC>staticno&test(...);// NB, on n'a pas besoin de définition, mais de renvoyer une réf.// Ici le compilo tente de résoudre. // Si T permet d'extraire un type `montype*`, alors on renvoie `yes` qui a une taille de 1// Sinon, on défaulte sur la version variadique qui renvoie un `no` de taille 2// Ce qui permet de construire le booléen `value` grâce à sizeof qui est toujours résolu à la compilationstaticconstboolvalue=sizeof(test<T>(NULL))==sizeof(yes);};structU{usingmontype=int;};intmain(){std::cout<<std::boolalpha;// affiche true ou falsestd::cout<<has_typedef_montype<int>::value<<"\n";std::cout<<has_typedef_montype<U>::value<<"\n";}
Façon C++14 (voire 17), on a de nouveaux outils:
#if 0// C++17// Requiert gcc 5.0template <typename...T> using void_t = void;#else// Pour gcc v < 5.0// Until CWG 1558 (a C++14 defect), unused parameters in alias templates// were not guaranteed to ensure SFINAE and could be ignored, so earlier// compilers require a more complex definition of void_t, such astemplate<typename...Ts>structmake_void{typedefvoidtype;};template<typename...Ts>usingvoid_t=typenamemake_void<Ts...>::type;#endif// Cas par défauttemplate<typenameT,typename=void>structhas_typedef_montype:std::false_type{};// Cas où l'on arrive à trouve le typedef qui nous intéressetemplate<typenameT>structhas_typedef_montype<T,void_t<typenameT::montype>>:std::true_type{};
[^] # Re: Je m'y colle...
Posté par lmg HS (site web personnel) . En réponse à la dépêche C++17 branche à la compilation (`if constexpr`). Évalué à 5.
Le SFINAE est un outil qui sert à détecter des informations non triviales ou des possibilités par essai et erreur. Sauf que les erreurs sont ignorées et à la place on se débrouille pour récupérer un truc que l'on va assimiler à faux. Ce booléen on s'en sert ensuite ailleurs pour choisir quelle spécialisation nous intéresse.
Exemple à la C++98
Façon C++14 (voire 17), on a de nouveaux outils: