2010-08-15 13 views
3

Désolé, je ne peux pas être plus précis dans le titre.Boost Multi_Index Question

Disons que j'ai une classe Foo

class Foo { 
public: 
    Foo() { m_bitset.reset(); } 

    void set_i(int i) { 
     m_bitset.set(1); 
     m_i = i; 
    } 

    void set_j(int j) { 
     m_bitset.set(2); 
     m_j = j; 
    } 
    bool i_set() { return m_bitset(1); } 
    bool j_set() { return m_bitset(2); } 
    void clear_i() { m_bitset.reset(1); } 
    void clear_j() { m_bitset.reset(2); } 
    int get_i() { 
     assert(i_set()); 
     return m_i; 
    } 
    int get_j() { 
     assert(j_set()); 
     return m_j; 
    } 

private: 
    int m_i, m_j; 
    bitset<2> m_bitset; 
}; 

Et maintenant, je veux mettre Foo dans un multi_index.

typedef multi_index_container < 
    Foo, 
    indexed_by< 
     ordered_non_unique<BOOST_MULTI_INDEX_CONST_MEM_FUN(Foo, int, get_i) 
     >, 
     ordered_non_unique<BOOST_MULTI_INDEX_CONST_MEM_FUN(Foo, int, get_j) 
     > 
    > 
> Foo_set; 

Ce que je suis en train de comprendre est un moyen d'avoir mon genre multi_index de Foo qui ont des valeurs valides de i ou j (ou les deux dans le cas d'un composite_key et passer au-dessus du reste. donc Je ne veux pas le code ci-dessous pour sauter, je veux juste revenir seulement foos qui ont des valeurs valides pour i.

for (Foo_set::nth_index<1>::type::iterator it = foos.get<1>().begin(); it != foos.get<1>().end(); ++it) 
    cout << *it; 

Répondre

1

de rasant la bibliothèque multi_index boost docs Je dirais que ce que vous voulez est pas En regardant son rationale il semble qu'il est seulement fait pour les éléments d'indexation qui sont entièrement indexables sur toutes les "dimensions". Vous pouvez essayer de demander à la liste de diffusion des utilisateurs de boost s'il y a des hacks pour autoriser des dimensions d'index "rares".)

De toute façon, en fonction de la nature exacte de votre problème, vous pourrez peut-être contourner ce problème en utilisant un boost: : optionnel comme type d'indexation. (Bien que je ne suis même pas sûr qu'il est possible d'indexer par boost :: en option.)

+0

Oui, il devrait être possible d'indexer avec 'boost :: optional'. – alfC

1

Avoir assert() dans vos fonctions get_i() et get_j() provoquera un arrêt difficile du programme quand multi_index demande pour les i ou j valeurs pour l'indexation.

Il semble que vous vouliez un comportement Null Object Pattern. C'est à dire. m_i et m_j sont des types de données qui prennent des valeurs spéciales pour indiquer qu'ils ne sont pas définis (s'ils étaient des pointeurs, le pointeur NULL servirait à cette fin). Alors votre multi-index pourrait indexer sur ces valeurs, regroupant toutes les valeurs null ensemble.

Lorsque vous accédez aux données, vous pouvez utiliser boost::range pour filtrer les valeurs nulles:

// Predicate for null testing 
struct is_not_null { 
    bool operator()(const Foo& f) { return f.get_i() != NULL && f.get_j() != NULL; } 
}; 

Foo_set::nth_index<1>::type& idx = foos.get<1>(); 
BOOST_FOREACH(const Foo& f, idx | filtered(is_not_null())) { 
    ;// do something with the non-null Foo's 
} 

Si vous ne voulez pas polluer la valeur de l'espace de vos variables (il n'y a pas de valeur null significative qui peut être stocké), vous pouvez également chercher à convertir vos membres m_i et m_j en boost::optional. Avec un peu plus de wrapper fonctor, vous pouvez créer un index composite de <bool, int>, ce qui vous permettrait d'accéder à Foo séparément. Vous pouvez également composer l'index pour combiner i et j avec un index composite qui ressemble à <bool, bool, int, int>.