2009-05-23 11 views
3

J'ai besoin d'un "conteneur" qui fonctionne comme suit. Il a 2 sous-conteneurs, appelés A et B, et je dois être capable de parcourir juste A, juste B, et A et B combinés. Je ne veux pas utiliser d'espace supplémentaire pour les données redondantes, j'ai donc pensé à faire de mon propre itérateur pour itérer A et B combinés. Quelle est la manière la plus simple de créer votre propre itérateur? Ou, quelle est une autre façon de faire cela?Créer un itérateur C++ qui traverse 2 conteneurs

EDIT En fin de compte, je ne pense pas que c'était un bon design. J'ai repensé toute la hiérarchie de la classe. +1 pour le refactoring Cependant, j'ai résolu ce problème suffisamment. Voici une version abrégée de ce que j'ai fait, pour référence; il utilise boost :: filter_iterator. Soit T le type dans le conteneur.

enum Flag 
{ 
    A_flag, 
    B_flag 
}; 

class T_proxy 
{ 
public: 
    T_proxy(const T& t, Flag f) : t_(t), flag_(f) {} 
    operator T() const {return t_;} 
    Flag flag() const {return flag_;} 
    class Compare 
    { 
    public: 
     Compare(Flag f) : matchFlag_(f) {} 
     operator() (const T_proxy& tp) {return tp.flag() == matchFlag_;} 
    private: 
     Flag matchFlag_; 
    }; 
private: 
    T t_; 
    Flag flag_; 
}; 

class AB_list 
{ 
public: 
    typedef T_proxy::Compare Compare; 
    typedef vector<T_proxy>::iterator iterator; 
    typedef boost::filter_iterator<Compare, iterator> sub_iterator; 
    void insert(const T& val, Flag f) {data_.insert(T_proxy(val, f));} 
    // other methods... 

    // whole sequence 
    iterator begin() {return data_.begin();} 
    iterator end() {return data_.end();} 

    // just A 
    sub_iterator begin_A() {return sub_iterator(Compare(A_flag), begin(), end()); 
    sub_iterator end_A() {return sub_iterator(Compare(A_flag), end(), end()); 

    // just B is basically the same 
private: 
    vector<T_proxy> data_; 
}; 


// usage 
AB_list mylist; 
mylist.insert(T(), A_flag); 
for (AB_list::sub_iterator it = mylist.begin_A(); it != mylist.end_A(); ++it) 
{ 
    T temp = *it; // T_proxy is convertible to T 
    cout << temp; 
} 

Répondre

7

Je rediffuser ma réponse à une question similaire. Je pense que cela fera ce que tu veux.

Utilisez une bibliothèque comme Boost.MultiIndex pour faire ce que vous voulez. Il évolue bien et il y a beaucoup moins de code de plaque de chaudière si vous voulez ajouter de nouveaux index. Il est également généralement more space and time efficient

typedef multi_index_container< 
    Container, 
    indexed_by< 
    sequenced<>, //gives you a list like interface 
    ordered_unique<Container, std::string, &Container::a_value>, //gives you a lookup by name like map 
    ordered_unique<Container, std::string, &Container::b_value> //gives you a lookup by name like map 
    > 
> container; 

Si vous itérez un index, vous pouvez passer à un autre index en utilisant le concept de projection iterator dans la bibliothèque.

+0

Boost.MultiIndex ne semble pas avoir un moyen d'exclure des éléments, cependant. – rlbond

0

Demandez un conteneur qui stocke la valeur que vous êtes intéressé avec un drapeau indiquant s'il est en A ou B.

0

Vous pouvez également créer un seul conteneur contenant des objets std :: pair <>.

Billy3

Questions connexes