2010-08-16 5 views
5

Bei dem Versuch, this question zu beantworten, wollte ich die Verwendung von enable_if + disable_if vorschlagen, um die Überladung einer Methode basierend auf der Tatsache zu ermöglichen, dass ein Typ (oder nicht) polymorph war.enable_if + disable_if Kombination provoziert einen mehrdeutigen Anruf

Also habe ich eine kleine Testdatei:

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; 
} 

, die ganz zahm scheint.

jedoch gcc (3.4 ...) Drossel dazu:

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]

Es scheint ziemlich klar zu meinem menschlichen Geist, die verwendet werden, hier überlasten sollte. Ich meine, es scheint klar zu sein, dass ich eine Alternative definiert habe und nur eine Funktion gleichzeitig verwendet werden kann ... und ich hätte gedacht, dass SFINAE dafür sorgen würde, die unnötige Überlastung zu entkräften.

Ich flickte es mit ... (Ellipse) anstelle von disable_if und erfordert ein Dummy-zweites Argument ... aber ich bin immer noch interessiert, warum der Compiler auf diesem zu ersticken.

Antwort

11

Der Compiler gedrosselt, weil Sie die Hinter ::type auf enable_if und disable_if vergessen. Die Vorlagen sind immer definiert. es ist nur, dass das Mitglied type vorhanden ist, wenn und nur wenn der Ausdruck true (für enable_if) oder false (für disable_if) ist.

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); } 

Ohne die Hinter ::type, Ihre Funktion Vorlagen erstellen, Überlastungen, die Zeiger auf Instanzen von enable_if oder disable_if als zweiten Parameter übernehmen. Mit dem nachlaufenden ::type erzeugen die Vorlagen entweder eine Überladung mit einem zweiten Parameter vom Typ void*, oder die Überladung wird entfernt (d. H. Das gewünschte Verhalten).

+0

Verdammt! Ich wusste, dass es funktionieren sollte ... –

0

die "Rückgabetyp" -Version von enable_if Verwendung arbeitet in 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; 
}