coup de pouce enable_if question C de
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
?
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;
};