2010-09-26 5 views
3

Est-ce que je peux simplifier les instructions suivantes? (probablement en utilisant boost::enable_if).C++ boost enable_if question

J'ai une structure simple de classe - Base classe de base, Derived1, Derived2 Hériter de Base.

J'ai le code suivant:

template <typename Y> struct translator_between<Base, Y> { 
    typedef some_translator<Base, Y> type; 
}; 

template <typename Y> struct translator_between<Derived1, Y> { 
    typedef some_translator<Derived1, Y> type; 
}; 

template <typename Y> struct translator_between<Derived2, Y> { 
    typedef some_translator<Derived2, Y> type; 
}; 

Je veux écrire la même déclaration en utilisant un modèle de spécialisation translator_between.

Un exemple (pseudo-code) de ce que je veux être en mesure d'écrire:

template <typename Class, typename Y> 

ONLY_INSTANTIATE_THIS_TEMPLATE_IF (Class is 'Base' or any derived from 'Base') 

struct translator_between<Class, Y> { 
    typedef some_translator<Class, Y> type; 
}; 

Toute façon d'y parvenir en utilisant boost::enable_if et boost::is_base_of?

Répondre

4

D'abord, vous aurez à choisir votre choix parmi:

  • is_base_of
  • is_convertible

les deux peuvent être foun d au <boost/type_traits.hpp>, ce dernier étant plus permissif.

Si vous avec pour éviter tout simplement l'instanciation de ce type pour une combinaison, puis utilisez un assert statique:

// C++03 
#include <boost/mpl/assert.hpp> 

template <typename From, typename To> 
struct translator_between 
{ 
    BOOST_MPL_ASSERT((boost::is_base_of<To,From>)); 
    typedef translator_selector<From,To> type; 
}; 

// C++0x 
template <typename From, typename To> 
struct translator_between 
{ 
    static_assert(boost::is_base_of<To,From>::value, 
       "From does not derive from To"); 
    typedef translator_selector<From,To> type; 
}; 

Comme il n'y a pas de résolution de surcharge qui se déroule ici, vous n'avez pas besoin enable_if.

4

Je ne pense pas que boost::enable_if aide, parce que SFINAE semble être plutôt sur le choix entre les surcharges de fonction.

Vous pouvez bien sûr utiliser des modèles avec bool paramètres pour affiner le choix:

#include <boost/type_traits.hpp> 
class Base {}; 

class Derived : public Base {}; 

template <class A, class B> 
struct some_translator {}; 

template <typename A, typename B, bool value> 
struct translator_selector; //perhaps define type as needed 

template <typename A, typename B> 
struct translator_selector<A, B, true> 
{ 
    typedef some_translator<A, B> type; 
}; 

template <typename A, typename B> 
struct translator_between 
{ 
    typedef typename translator_selector<A, B, boost::is_base_of<Base, A>::value>::type type; 
}; 

int main() 
{ 
    translator_between<Base, int>::type a; 
    translator_between<Derived, int>::type b; 
    translator_between<float, int>::type c; //fails 
} 
0

Vous pouvez utiliser cette macro anable_if et ici pour le rendre plus lisible:

#define CLASS_REQUIRES(...) typename boost::enable_if<boost::mpl::and_<__VA_ARGS__, boost::mpl::bool_<true> > >::type 

Ensuite, vous pouvez définir votre classe comme ceci:

template <typename Class, typename Y, class Enable = 
CLASS_REQUIRES(boost::is_base_of<Class, Y>)> 
struct translator_between { 
    typedef some_translator<Class, Y> type; 
}; 
Questions connexes