2012-01-28 4 views
0

J'ai un Boost.BiMap privé dans une classe, et je voudrais exporter une vue publique d'une partie de cette carte. J'ai deux questions sur le code suivant:Exposer la vue publique de Boost.BiMap itérateur en privé

class Object { 

    typedef bimap< 
     unordered_set_of<Point>, 
     unordered_multiset_of<Value> 
    > PointMap; 

    PointMap point_map; 

public: 
    ??? GetPoints(Value v) { 
    ... 
} 

La première question est de savoir si ma méthode d'itération pour obtenir les associés à une Value « s Point est correct. Voici le code que j'utilise pour itérer sur les points. Ma question est si je suis itératif correctement parce que j'ai trouvé que je devais inclure la condition it->first == value, et n'était pas sûr si cela était exigé donné une meilleure interface que je peux ne pas savoir.

PointMap::right_const_iterator it; 
it = point_map.right.find(value); 
while (it != point_map.right.end() && it->first == val) { 
    /* do stuff */ 
} 

La deuxième question est quelle est la meilleure façon de fournir une vue du public des GetPoints (type ??? de retour ci-dessus) sans exposer le iterator bimap car il semble que l'appelant aurait à connaître point_map.right.end(). Toute structure efficace telle qu'une liste de références ou un ensemble fonctionnerait, mais je suis un peu perdu sur la façon de créer la collection.

Merci!

Répondre

0

La première question:

Puisque vous utilisez le type de collection unordered_multiset_of pour le côté droit de votre type de bimap, cela signifie qu'il aura une interface compatible avec std::unordered_multimap. std::unordered_multimap a la fonction membre equal_range(const Key& key) qui renvoie un std::pair d'itérateurs, l'un pointant vers le premier élément qui a la clé désirée et l'autre vers la fin de la plage d'éléments ayant la même clé. En utilisant cela, vous pouvez parcourir la plage avec la clé correspondante sans comparer la clé à la valeur dans la condition d'itération.

Voir http://www.boost.org/doc/libs/1_41_0/libs/bimap/doc/html/boost_bimap/the_tutorial/controlling_collection_types.html et http://en.cppreference.com/w/cpp/container/unordered_multimap/equal_range pour les références.

La deuxième question:

Construire une liste ou un autre conteneur réel de pointeurs ou références aux éléments avec les valeurs correspondantes et le retour qui est inefficace car il va toujours besoin d'espace O (n), alors que le simple fait de laisser l'utilisateur itérer sur la plage dans le bimap d'origine nécessite seulement de renvoyer deux itérateurs, qui ne nécessitent que de la mémoire O (1).

Vous pouvez écrire une fonction membre qui renvoie directement les itérateurs, par ex.

typedef PointMap::right_const_iterator match_iterator; 

std::pair<match_iterator, match_iterator> GetPoints(Value v) { 
    return point_map.right.equal_range(v); 
} 

ou vous pouvez écrire une classe proxy qui présente une interface de type conteneur en ayant begin() et à la fin() fonctions membres retournant ces deux itérateurs, et votre fonction membre GetPoints() retourne un objet de ce type:

class MatchList { 

    typedef PointMap::right_const_iterator iterator; 

    std::pair<iterator, iterator> m_iters; 

public: 

    MatchList(std::pair<iterator, iterator> const& p) : m_iters(p) {} 

    MatchList(MatchList const&) = delete; 

    MatchList(MatchList&&) = delete; 

    MatchList& operator=(MatchList const&) = delete; 

    iterator begin() { return m_iters.first; } 

    iterator end() { return m_iters.second; } 
}; 

il est une bonne idée de le faire incopiables, inébranlables et incessible (comme je l'ai fait ci-dessus en supprimant les fonctions membres concernés) car l'utilisateur peut par ailleurs conserver une copie de la classe proxy et essayez d'y accéder plus tard, lorsque les itérateurs pourraient être invalidés. Le premier moyen consiste à écrire moins de code, le second moyen présente une interface plus commune à l'utilisateur (et permet de cacher plus de choses dans la classe proxy si vous avez besoin de modifier l'implémentation plus tard).

+0

En ce qui concerne la première approche de la deuxième question, est-ce que PointMap doit être publicisé? Puis-je utiliser un type d'itérateur générique pour l'interface publique? –

+0

PointMap peut toujours être privé. Le typedef match_iterator dans mon exemple de code doit être public afin qu'il puisse être utilisé par du code en dehors de la classe. – user450018

Questions connexes