2010-08-04 14 views
5

Je pourrais bien sûr utiliser is_base si la classe de base n'était pas un modèle. Cependant, quand c'est le cas, je ne vois aucun moyen de faire correspondre génériquement n'importe quel type dérivé. Voici un exemple de base de ce que je veux dire:Est-il possible de faire correspondre la base modèle dans les spécialisations de modèle?

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

Je veux que revenir true_ plutôt que false_. L'exemple réel a comme 7 paramètres de modèle, la plupart par défaut, et utilise Boost.Parameter pour s'y référer par son nom. Afin d'utiliser is_base je devrais être en mesure de tirer les paramètres en quelque sorte et je ne vois pas un moyen de faire cela à court de déclarer les typedefs internes.

Je pense que c'est impossible. Vous cherchez à avoir tort.

+1

peut vous présenter le type de marqueur unique dans la base de test et l'activation/désactivation basé sur cela? – Anycorn

+0

C'est une option viable que j'aurais dû penser à moi-même. Toujours intéressé si quelqu'un peut trouver un moyen de contourner sans cela si. –

+0

@aaa - vous devriez en faire une réponse. J'ai l'impression que c'est la seule méthode possible, alors dans quelques jours après que je ne reçois aucune réponse, vous pouvez aussi obtenir un crédit pour cela. –

Répondre

3

Vous avez juste besoin de modifier votre test un peu:

#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

Excellent! SFINAE à la rescousse encore une fois. –

+0

SFINAE n'est pas impliqué ici, juste une surcharge de fonction pure. C'est à dire. l'instanciation de do_test (base de test *) ne produit jamais d'erreur. –

0

Ici. Vous pouvez changer is_base_and_derived pour is_same, selon les besoins.

#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

Merci, mais ... Cela ne fonctionne que si vous lui passez quelque chose dérivé de test_base , cela ne fonctionne pas pour une base de test. L'objet doit correspondre à tout ce qui est dérivé de n'importe quelle instanciation de test_base. –

+0

Ish, désolé je suis allé trop vite. Ensuite, je ne vois pas comment vous pourriez faire ça. Événement si c'est moche, peut-être une alternative serait d'ajouter une interface vide pour faire votre is_base_and_derived. –