2010-08-04 13 views
5

Podría, por supuesto, usar is_base si la clase base no es una plantilla. Sin embargo, cuando lo es, simplemente no veo ninguna forma de hacer coincidir genéricamente ningún tipo derivado. Aquí hay un ejemplo básico de lo que quiero decir:¿Es posible hacer coincidir la base de plantilla en las especializaciones de plantilla?

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

Quiero que volver a true_ en lugar de false_. El ejemplo real tiene como 7 parámetros de plantilla, la mayoría de ellos predeterminados, y usa Boost.Parameter para referirse a ellos por su nombre. Para usar is_base tendría que ser capaz de extraer los parámetros de alguna manera y no veo una manera de hacerlo menos de declarar typedefs internos.

Creo que es imposible. Buscando ser probado equivocado.

+1

puede presentarle tipo de etiqueta única en la base de prueba y desactivar/activar basa en eso? – Anycorn

+0

Esa es una opción viable que debería haber pensado de mí mismo. Sin embargo, todavía está interesado si alguien puede encontrar un camino sin él. –

+0

@aaa - deberías hacer una respuesta. Tengo la sensación de que es el único método posible, así que en un par de días después de que no recibo una respuesta, es mejor que me den crédito por ello. –

Respuesta

3

Sólo tiene que ajustar su prueba un poco:

#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

¡Excelente! SFINAE al rescate una vez más. –

+0

SFINAE no está involucrado aquí, solo sobrecarga de función pura. Es decir. instanciar do_test (test_base *) nunca produce un error. –

0

Aquí. Puede cambiar is_base_and_derived para is_same, según las necesidades.

#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

Gracias, pero ... Eso solo funciona si le pasa algo derivado de test_base , no funciona para ningún test_base. Object es hacer coincidir cualquier cosa derivada de cualquier instanciación de test_base. –

+0

Ish, lo siento, fui demasiado rápido. Entonces, simplemente no veo cómo podrías hacer eso. Evento si es feo, tal vez una alternativa sería agregar una interfaz vacía para hacer su is_base_and_derived en. –

Cuestiones relacionadas