Question

Dois-je un moyen de simplifier les déclarations suivantes? (probablement, en utilisant boost::enable_if) .

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

Je 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;
};

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

Était-ce utile?

La solution

Tout d'abord, vous devrez choisir votre choix parmi:

  • is_base_of
  • is_convertible

Les deux se trouve dans <boost/type_traits.hpp>, ce dernier étant plus permissive.

Si vous avec pour simplement empêcher 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 surcharge lieu ici, vous n'avez pas besoin enable_if.

Autres conseils

Je pense Don''t boost::enable_if aide, parce que SFINAE semble être plutôt sur le choix entre la fonction de surcharge.

Vous pouvez utiliser des modèles de cours avec des paramètres de bool 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
}

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;
};
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top