2010-08-16 2 views
5

ambiguë Tout en essayant de répondre à this question 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 était (ou non) polymorphes.enable_if + disable_if combinaison provoque un appel

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 apprivoisé.

Cependant gcc (3.4 ...) étrangleur sur ce point:

test.cpp: In function int main(int, char**) :
test.cpp:29: error: call of overloaded address_of(N*) is ambiguous
test.cpp:17: note: candidates are: void* address_of(T*, boost::enable_if<boost::is_polymorphic<T>, void>*) [with T = N]
test.cpp:20: note: void* address_of(T*, boost::disable_if<boost::is_polymorphic<T>, void>*) [with T = N]

Il semble assez clair à mon esprit humain qui surcharge doit être utilisé ici. Je veux dire qu'il semble clair que j'ai défini une alternative et qu'une seule fonction peut être utilisée à la fois ... et j'aurais pensé que SFINAE prendrait soin d'invalider la surcharge inutile.

Je l'ai patché en utilisant ... (points de suspension) au lieu de disable_if et nécessitant un second argument fictif ... mais je suis toujours intéressé par la raison pour laquelle le compilateur s'étouffe.

Répondre

11

Le compilateur étranglé parce que vous avez oublié le ::type de fuite sur enable_if et disable_if. Les modèles sont toujours définis. c'est juste que le membre type 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 fin, les modèles créent une surcharge avec un second paramètre de type void*, ou la surcharge est supprimée (c'est-à-dire le comportement souhaité).

+0

Damned! Je savais que ça devrait marcher ... –

0

Utilisation de la version de enable_if "type de 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; 
} 
Questions connexes