2010-08-04 9 views
5

Potrei ovviamente usare is_base se la classe base in cui non è un modello. Tuttavia, quando lo è, non vedo alcun modo per abbinare genericamente qualsiasi tipo derivato. Ecco un esempio di base di ciò che intendo:È possibile abbinare la base basata su modello nelle specializzazioni di modelli?

#include <boost/mpl/bool.hpp> 

template < typename T > 
struct test_base 
{ 
}; 

template < typename T > 
struct check : boost::mpl::false_ {}; 

template < typename T > 
struct check<test_base<T> > : boost::mpl::true_ {}; 

struct test_derived : test_base<int> {}; 

#include <iostream> 
int main() 
{ 
    std::cout << check<test_derived>::value << std::endl; 
    std::cin.get(); 
} 

voglio che per tornare true_ piuttosto che false_. L'esempio reale ha come 7 parametri di modello, la maggior parte di default, e usa Boost.Parameter per riferirsi ad essi per nome. Per poter utilizzare is_base avrei dovuto essere in grado di tirare i parametri in qualche modo e non vedo un modo di fare che a corto di dichiarazione typedef interni.

penso che sia impossibile. Cercando di essere smentiti.

+1

è possibile introdurre unico tipo di tag nella base di prova e abilitare/disabilitare basano su questo? – Anycorn

+0

Questa è una valida opzione che avrei dovuto pensare a me stesso. Ancora interessato se chiunque può trovare un modo per aggirare senza però. –

+0

@aaa - dovresti fare una risposta. Hai la sensazione che sia l'unico metodo possibile, quindi in un paio di giorni dopo che non avrò risposta potresti anche averne il merito. –

risposta

3

Hai solo bisogno di modificare il test un po ':

#include <iostream> 
#include <boost/mpl/bool.hpp> 

template < typename T > 
struct test_base 
{ 
}; 

template < typename T > 
struct check_ 
{ 
    template<class U> 
    static char(&do_test(test_base<U>*))[2]; 
    static char(&do_test(...))[1]; 
    enum { value = 2 == sizeof do_test(static_cast<T*>(0)) }; 
}; 

template < typename T > 
struct check : boost::mpl::bool_<check_<T>::value> {}; 

struct test_derived : test_base<int> {}; 

int main() 
{ 
    std::cout << check<test_derived>::value << std::endl; 
} 
+0

Eccellente! SFINAE in soccorso ancora una volta. –

+0

SFINAE non è coinvolto qui, solo puro sovraccarico delle funzioni. Cioè istanziazione do_test (test_base *) non produce mai un errore. –

0

Qui. Puoi cambiare is_base_and_derived per is_same, a seconda delle esigenze.

#include "boost/mpl/equal.hpp" 
#include "boost/mpl/vector.hpp" 
#include <boost/utility/enable_if.hpp> 
#include "boost/type_traits/is_base_and_derived.hpp" 
#include <boost/function_types/function_type.hpp> 

using namespace boost; 

template < typename T > 
struct test_base 
{ 
}; 

struct test_derived : test_base<int> {}; 


//The default case 
template<class T, class Enable =void> 
class check : public boost::mpl::false_ {}; 

//The specified case 
template<class T> 
class check<T, typename boost::enable_if< 
     boost::is_base_and_derived<test_base<int>,T> 
    >::type>: public boost::mpl::true_ 
{}; 


#include <iostream> 
int main() 
{ 
    std::cout << check<test_derived>::value << std::endl; 
    std::cin.get(); 
} 
+0

Grazie, ma ... che funziona solo se si passa qualcosa derivato da test_base , non funziona per qualsiasi test_base. L'oggetto è abbinare qualsiasi cosa derivata da qualsiasi istanziazione di test_base. –

+0

Ish, scusa sono andato troppo veloce. Quindi non vedo come potresti farlo. Evento se è brutto, forse un'alternativa sarebbe quella di aggiungere un'interfaccia vuota per fare il tuo is_base_and_derived su. –

Problemi correlati