boost :: multi_index_container, opérations sur std :: set à l’intérieur du conteneur

J’ai créé un boost :: multi_index_container ( containerSet ) sur une classe de conteneur et indexé le containerSet par std::ssortingng et std::set . Est-il possible d’obtenir le conteneur, qui stocke un int spécifique dans leur ensemble? En outre, est-il possible d’obtenir tous les conteneurs qui stockent au moins une valeur entre int1 et int2 dans leur ensemble?

 #include  #include  #include  #include  #include  #include  #include  using boost::multi_index_container; using namespace boost::multi_index; class Container { public: std::set set; std::ssortingng name; Container(std::ssortingng name, std::set set); ~Container(); friend std::ostream& operator<<(std::ostream& os,const Container& c) { os << c.name << ", [ "; for (int i : c.set) { os << i << " "; } os << "]"; return os; } }; Container::Container(std::string name = "noName", std::set set = {}) : name{name} ,set{set} {} Container::~Container() {} struct setTag{}; struct nameTag{}; typedef multi_index_container<Container, indexed_by< ordered_unique<tag, BOOST_MULTI_INDEX_MEMBER(Comp, std::ssortingng, name)>, ordered_unique<tag, BOOST_MULTI_INDEX_MEMBER(Comp, std::set, set)> >> ContainerSet; //don't see how I could get the compare structs to work, because //a) can't fullfill the ssortingct weak odering requirements and //b) because of the setTag ordering, not all set's get called struct compSetRange { bool operator()(int x,const std::set &c) const {} bool operator()(const std::set &c, int x) const {} }; struct compSetFind { bool operator()(int x,const std::set &c) const {} bool operator()(const std::set &c, int x) const {} }; int main() { Container c1{"c1", {5, 6, 7, 18, 61, 77}}; Container c2{"c2", {2, 4, 5, 21, 36, 88, 99}}; Container c3{"c3", {2, 3, 9, 10, 65, 75, 91}}; ContainerSet cs; cs.insert(c1); cs.insert(c2); cs.insert(c3); std::cout << "print by name (ordered)" << std::endl; for (auto e : cs.get()) { std::cout << e << std::endl; } std::cout << std::endl; std::cout << "print by set (ordered)" << std::endl; for (auto e : cs.get()) { std::cout << e << std::endl; } std::cout << std::endl; typedef ContainerSet::index::type compBySetIndex; //find(std::set) works but isn't useful in my case compBySetIndex::iterator it1 = cs.get().find(std::set{2, 4, 5, 21, 36, 88, 99}); //TODO: find all comps with int 5 -> c1 and c2 // compBySetIndex::iterator it1 = cs.get().find(200, compSetFind()); if (it1 !=cs.get().end()) { std::cout << *it1 < c1 and c3 // compBySetIndex::iterator it1_low = cs.get().lower_bound(70, compSetRange()); // compBySetIndex::iterator it1_upp = cs.get().upper_bound(80, compSetRange()); //.range() also not applicable return 0; } 

Avec les sets:
c3 = {2, 3, 9, 10, 65, 75, 91}
c2 = {2, 4, 5, 21, 36, 88, 99}
c1 = {5, 6, 7, 18, 61, 77}
Je veux pouvoir appeler ...find(5); et obtenez au moins c2 , voire même c1 lors de la prochaine invocation. Cela pourrait être faisable avec la fonction de comparaison appropriée, mais je ne vois pas comment rendre les fonctions de l’opérateur () compatibles .
De plus, après ...lower_bounds(70) et ...upper_bounds(80) je devrais avoir c3 et c1 . En raison de la commande de std :: set, cette exigence semble irréalisable avec boost.

Est-ce que je manque quelque chose? Merci d’avance!


Je sais que je pourrais effectuer une recherche linéaire sur tous les conteneurs et leurs ensembles pour atteindre mon objective, mais cela annulerait l’avantage en termes de performances du multi_index_container. Si boost est le mauvais outil pour ce travail, je devrai recourir à un class containerSet individuelle.

Andrew a diagnostiqué le problème assez précisément.

Pour vous aider, laissez-moi vous annoncer une bibliothèque largement sous-utilisée dans Boost: Boost Interval Container.

J’espère que cette démo pourra vous éclairer sur l’utilité de Boost ICL.

Live On Coliru

 #include  #include  #include  #include  #include  #include  #include  #include  using Set = std::set; struct io_wrap { Set const& ref; }; static std::ostream& operator<<(std::ostream& os,const io_wrap& s) { os << "[ "; for (auto i : s.ref) os << i << " "; return os << ']'; } namespace icl = boost::icl; namespace bmi = boost::multi_index; struct Record { std::string name; Set set; Record(std::string name = "noName", Set set = {}) : name{name}, set{set} {} friend std::ostream& operator<<(std::ostream& os,const Record& c) { return os << c.name << ", " << io_wrap{c.set}; } }; using Map = icl::interval_map >; using Interval = Map::interval_type; using Table = bmi::multi_index_container< std::reference_wrapper, bmi::indexed_by< bmi::ordered_unique< bmi::tag, bmi::member > > >; auto interval_set(Set const& is) { return std::accumulate(is.begin(), is.end(), icl::interval_set { } ); } auto envelope(Record const& r) { return hull(interval_set(r.set)); } void insert(Map& into, Set const& is, std::set const& rs = {}) { for (auto i : interval_set(is)) into += Map::value_type { i, rs }; } int main() { //////////////////////////////// // Prepare data std::vector backing_storage { {"c3", {2, 3, 9, 10, 65, 75, 91}}, {"c1", {5, 6, 7, 18, 61, 77}}, {"c2", {2, 4, 5, 21, 36, 88, 99}}, // outliers {"c4", {0}}, {"c5", {200}}, }; Table const byname(backing_storage.begin(), backing_storage.end()); Map cs; for (auto& r : backing_storage) insert(cs, r.set, { &r }); //////////////////////////////// // Usage demos std::cout << "print by name (ordered)\n"; for (auto const& e : byname) { std::cout << " - " << e << " - envelope: " << envelope(e) << "\n"; } std::cout << "\n"; auto perform_match = [&cs](auto key) { Map::codomain_type matches; Map::codomain_combine combine; for (auto p : cs & key) combine(matches, p.second); std::cout << "matching " << key << ":\n"; for (auto const* r : matches) std::cout << " - " << *r << "\n"; std::cout << "\n"; }; for (auto key : { Set{2}, {99}, {2,99}, {2,99,5} }) { perform_match(interval_set(key)); } perform_match(Interval::right_open(70, 81)); } 

Impressions:

 print by name (ordered) - c1, [ 5 6 7 18 61 77 ] - envelope: [5,77] - c2, [ 2 4 5 21 36 88 99 ] - envelope: [2,99] - c3, [ 2 3 9 10 65 75 91 ] - envelope: [2,91] - c4, [ 0 ] - envelope: [0,0] - c5, [ 200 ] - envelope: [200,200] matching {[2,2]}: - c3, [ 2 3 9 10 65 75 91 ] - c2, [ 2 4 5 21 36 88 99 ] matching {[99,99]}: - c2, [ 2 4 5 21 36 88 99 ] matching {[2,2][99,99]}: - c3, [ 2 3 9 10 65 75 91 ] - c2, [ 2 4 5 21 36 88 99 ] matching {[2,2][5,5][99,99]}: - c3, [ 2 3 9 10 65 75 91 ] - c1, [ 5 6 7 18 61 77 ] - c2, [ 2 4 5 21 36 88 99 ] matching [70,81): - c3, [ 2 3 9 10 65 75 91 ] - c1, [ 5 6 7 18 61 77 ]