2010-06-28 10 views
3

J'ai une liste des types définis comme:Utiliser boost :: :: mpl lambda pour supprimer des types d'un boost :: :: mpl liste basée sur la variable membre const statique

typedef boost::mpl::list<Apple, Pear, Brick> OriginalList; 

Je voudrais créer une deuxième liste qui ne contient aucun fruit, c'est-à-dire que la liste résultante formée à partir de la première liste contiendrait un seul type de brique. Le fruit est identifié par une variable statique const définie dans les types, par exemple .:

struct Apple 
{ 
    static const bool IsFruit = true; 
}; 

J'ai actuellement une solution qui implique la création d'une classe méta-fonction, et en utilisant boost::mpl::remove_if. Je crois que je devrais être en mesure de rendre cela plus élégant en utilisant boost :: mpl :: lambda pour supprimer le besoin de la structure séparée RemoveFruit. Des suggestions sur la façon de faire cela?

code complet tel qu'il se présente actuellement:

include <boost/static_assert.hpp> 
#include <boost/mpl/list.hpp> 
#include <boost/mpl/remove_if.hpp> 
#include <boost/mpl/size.hpp> 

#include <iostream> 

struct Apple 
{ 
    static const bool IsFruit = true; 
}; 

struct Pear 
{ 
    static const bool IsFruit = true; 
}; 

struct Brick 
{ 
    static const bool IsFruit = false; 
}; 

typedef boost::mpl::list<Apple, Pear, Brick> OriginalList; 
BOOST_STATIC_ASSERT(boost::mpl::size<OriginalList>::type::value == 3); 

// This is what I would like to get rid of: 
struct RemoveFruit 
{ 
    template <typename T> 
    struct apply 
    { 
    typedef boost::mpl::bool_<T::IsFruit> type; 
    }; 
}; 

// Assuming I can embed some predicate directly in here? 
typedef boost::mpl::remove_if< 
    OriginalList, 
    RemoveFruit 
    >::type NoFruitList; 

BOOST_STATIC_ASSERT(boost::mpl::size<NoFruitList>::type::value == 1); 

int main() 
{ 
    std::cout << "There are " << boost::mpl::size<OriginalList>::type::value << " items in the original list\n"; 
    std::cout << "There are " << boost::mpl::size<NoFruitList>::type::value << " items in the no fruit list\n"; 


    return 0; 
} 
+0

souhaite que nous avions un débogueur méta-modèle. :-D – stinky472

Répondre

3

Je pense que le mieux que vous pouvez faire est de définir une struct IsFruit comme

template <typename T> struct isFruit : boost::mpl::bool_<T::IsFruit> {}; 

Et vous pouvez alors définir votre liste d'interdiction de fruits comme

typedef boost::mpl::remove_if< 
    OriginalList, 
    boost::mpl::lambda< isFruit<boost::mpl::_1> >::type 
    >::type NoFruitList; 

La structure supplémentaire est nécessaire pour accéder au champ IsFruit de vos classes.

Notez que si vous voulez vous débarrasser entièrement de la structure supplémentaire, vous devrez renommer les membres booléens de vos autres classes. Si vous suivez le boost :: convention de mpl et de les appeler value au lieu de IsFruit, vous pouvez définir NoFruitList comme

typedef boost::mpl::remove_if< 
     OriginalList, 
     boost::mpl::lambda<boost::mpl::_1>::type 
     >::type NoFruitList; 
+0

C'est parfait. Merci. Juste une question de suivi rapide. Je ne peux pas renommer IsFruit en valeur, mais serait-il possible de changer le type d'un 'static const bool' en un' boost :: mpl :: bool _ <> 'et d'accéder à la valeur de cette façon? – Shane

+0

Malheureusement, je ne connais aucun moyen de faire ce travail. Essentiellement, le nom 'value' est utilisé en interne par les algorithmes mpl pour obtenir n'importe quel champ de valeur (tout comme 'type' est utilisé pour obtenir des champs de type). Dans ce cas, lambda utilisera le champ value pour générer une classe metafunction qui a le même effet que votre metafunction RemoveFruit. Si vous ne pouvez pas renommer, vous avez besoin d'un autre mécanisme pour indiquer à mpl le champ que vous voulez utiliser. Dans mon exemple, ce serait la structure isFruit qui mappe essentiellement le champ IsFruit de vos classes au champ de valeur de bool_. – JRM

+0

Assez juste. Merci. – Shane