2010-08-16 14 views
5

Durante il tentativo di rispondere this question ho voluto suggerire l'uso di enable_if + disable_if per consentire il sovraccarico di un metodo basato sul fatto che un tipo è (o non) polimorfica.enable_if + disable_if combinazione provoca una chiamata ambigua

così ho creato un piccolo file di 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; 
} 

che sembra piuttosto noiosi.

Tuttavia gcc (3,4 ...) starter su questo:

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]

sembra piuttosto chiaro alla mia mente umana che sovraccaricare dovrebbe essere usato qui. Voglio dire, sembra chiaro che ho definito un'alternativa e solo una funzione può essere utilizzata in un momento ... e avrei pensato che SFINAE si sarebbe preoccupata di invalidare il sovraccarico non necessario.

L'ho rattoppato usando ... (puntini di sospensione) anziché disable_if e richiedendo un secondo argomento fittizio ... ma sono ancora interessato al motivo per cui il compilatore soffoca su questo.

risposta

11

Il compilatore soffocato perché si è dimenticato il finale ::type su enable_if e disable_if. I modelli sono sempre definiti; è solo che il membro type è presente se e solo se l'espressione è true (per enable_if) o false (per 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); } 

Senza la finale ::type, i modelli di funzione basta creare sovraccarichi che prendono puntatori a istanze di enable_if o disable_if come secondo parametro. Con il trailing ::type, i modelli creano un sovraccarico con un secondo parametro di tipo void* oppure il sovraccarico viene rimosso (ovvero il comportamento desiderato).

+0

Dannato! Sapevo che avrebbe dovuto funzionare ... –

0

Utilizzando la versione "tipo di ritorno" di enable_if lavora 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; 
} 
Problemi correlati