enable_if + disable_if combinaison provoque un appel ambigu
Question
Tout en essayant de répondre à cette question que je voulais suggérer l'utilisation de enable_if
+ disable_if
pour permettre la surcharge d'une méthode basée sur le fait qu'un type est (ou non) polymorphique.
Je créé un petit fichier de test:
template <class T>
void* address_of(T* p,
boost::enable_if< boost::is_polymorphic<T> >* dummy = 0)
{ return dynamic_cast<void*>(p); }
template <class T>
void* address_of(T* p,
boost::disable_if< boost::is_polymorphic<T> >* dummy = 0)
{ return static_cast<void*>(p); }
struct N { int x; };
int main(int argc, char* argv[])
{
N n;
std::cout << address_of(&n) << std::endl;
return 0;
}
qui semble tout à fait dompter.
Cependant gcc (3.4 ...) étouffer ceci:
test.cpp: En fonction
int main(int, char**)
:
test.cpp: 29: Erreur: appel deaddress_of(N*)
surchargé est ambigu
test.cpp: 17: Note: Les candidats sont:void* address_of(T*, boost::enable_if<boost::is_polymorphic<T>, void>*)
[avec T = N]
test.cpp: 20: Note:void* address_of(T*, boost::disable_if<boost::is_polymorphic<T>, void>*)
[avec T = N]
Il semble assez clair à mon esprit humain qui surcharge doit être utilisé ici. Je veux dire, il semble clair que je l'ai défini une alternative et une seule fonction peut être utilisée à la fois ... et je l'aurais pensé que SFINAE prendrait soin de vicier la surcharge inutile.
Je patché vers le haut à l'aide ...
(points de suspension) au lieu de disable_if
et nécessitant un second argument factice ... mais je suis toujours intéressé à savoir pourquoi le starter du compilateur à ce sujet.
La solution
Le compilateur étranglé parce que vous avez oublié le ::type
de fin sur enable_if
et disable_if
. Les modèles sont toujours définis; il est juste que le type
membre est présent si et seulement si l'expression est true
(pour enable_if
) ou false
(pour disable_if
).
template <class T>
void* address_of(T* p,
typename boost::enable_if< boost::is_polymorphic<T> >::type* dummy = 0)
{ return dynamic_cast<void*>(p); }
template <class T>
void* address_of(T* p,
typename boost::disable_if< boost::is_polymorphic<T> >::type* dummy = 0)
{ return static_cast<void*>(p); }
Sans ::type
arrière, vos modèles de fonction créer simplement des pointeurs qui prennent des surcharges aux instances de enable_if
ou disable_if
comme second paramètre. Avec le ::type
de fuite, les modèles, soit créer une surcharge avec un deuxième paramètre de type void*
, ou la surcharge est retiré (à savoir le comportement souhaité).
Autres conseils
En utilisant la version de enable_if type "retour" fonctionne dans 3.4.4: gcc version 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_polymorphic.hpp>
#include <iostream>
template <class T>
typename boost::enable_if< boost::is_polymorphic<T>, void* >::type
address_of(T* p)
{ return dynamic_cast<void*>(p); }
template <class T>
typename boost::disable_if< boost::is_polymorphic<T>, void* >::type
address_of(T* p)
{ return static_cast<void*>(p); }
struct N { int x; };
int main(int argc, char* argv[])
{
N n;
std::cout << address_of(&n) << std::endl;
return 0;
}