Boost.MultiIndex. Using several keys together.

Hello, there's a structure struct person { std::string name; std::string surname; int birth_year; std::string craft; }; How to create such a multiindex container that dumping could performed using an index as name, surname and year triple alltogether? -- View this message in context: http://boost.2283326.n4.nabble.com/Boost-MultiIndex-Using-several-keys-toget... Sent from the Boost - Users mailing list archive at Nabble.com.

On 02/04/2014 03:36 PM, syvyi wrote:
Hello,
there's a structure struct person { std::string name; std::string surname; int birth_year; std::string craft; };
How to create such a multiindex container that dumping could performed using an index as name, surname and year triple alltogether? Sounds like you might be interested in MultiIndex's composite key feature:
http://www.boost.org/doc/libs/1_55_0/libs/multi_index/doc/tutorial/key_extra... Jason

What if the composite key should be parameterized from a file? In the case of <raw> struct phonebook_entry{ std::string family_name; std::string given_name; std::string phone_number; phonebook_entry( std::string family_name, std::string given_name, std::string phone_number): family_name(family_name),given_name(given_name),phone_number(phone_number) {}}; // define a multi_index_container with a composite key on // (family_name,given_name)typedef multi_index_container< phonebook_entry, indexed_by< //non-unique as some subscribers might have more than one number ordered_non_unique< composite_key< phonebook_entry, member<phonebook_entry,std::string,&phonebook_entry::family_name>, member<phonebook_entry,std::string,&phonebook_entry::given_name> > >, ordered_unique< // unique as numbers belong to only one subscriber member<phonebook_entry,std::string,&phonebook_entry::phone_number> >
phonebook;
</raw> the lines member<phonebook_entry,std::string,&phonebook_entry::family_name>, member<phonebook_entry,std::string,&phonebook_entry::given_name> should be auto-generated by reading a composite key from a file. 2014-02-04 Jason [via Boost] <ml-node+s2283326n4658955h57@n4.nabble.com>:
On 02/04/2014 03:36 PM, syvyi wrote:
Hello,
there's a structure struct person { std::string name; std::string surname; int birth_year; std::string craft; };
How to create such a multiindex container that dumping could performed using an index as name, surname and year triple alltogether? Sounds like you might be interested in MultiIndex's composite key feature:
http://www.boost.org/doc/libs/1_55_0/libs/multi_index/doc/tutorial/key_extra...
Jason _______________________________________________ Boost-users mailing list [hidden email] <http://user/SendEmail.jtp?type=node&node=4658955&i=0> http://lists.boost.org/mailman/listinfo.cgi/boost-users
------------------------------ If you reply to this email, your message will be added to the discussion below:
http://boost.2283326.n4.nabble.com/Boost-MultiIndex-Using-several-keys-toget... To unsubscribe from Boost.MultiIndex. Using several keys together., click here<http://boost.2283326.n4.nabble.com/template/NamlServlet.jtp?macro=unsubscribe_by_code&node=4658953&code=YWxleGFuZGVyLnN2a0BnbWFpbC5jb218NDY1ODk1M3wxMzU1MTY0OTM5> . NAML<http://boost.2283326.n4.nabble.com/template/NamlServlet.jtp?macro=macro_viewer&id=instant_html%21nabble%3Aemail.naml&base=nabble.naml.namespaces.BasicNamespace-nabble.view.web.template.NabbleNamespace-nabble.view.web.template.NodeNamespace&breadcrumbs=notify_subscribers%21nabble%3Aemail.naml-instant_emails%21nabble%3Aemail.naml-send_instant_email%21nabble%3Aemail.naml>
-- View this message in context: http://boost.2283326.n4.nabble.com/Boost-MultiIndex-Using-several-keys-toget... Sent from the Boost - Users mailing list archive at Nabble.com.

On 02/04/2014 04:35 PM, syvyi wrote:
What if the composite key should be parameterized from a file?
In the case of <raw> struct phonebook_entry { std::string family_name; std::string given_name; std::string phone_number;
phonebook_entry( std::string family_name, std::string given_name, std::string phone_number): family_name(family_name),given_name(given_name),phone_number(phone_number) {} };
// define a multi_index_container with a composite key on // (family_name,given_name) typedef multi_index_container< phonebook_entry, indexed_by< //non-unique as some subscribers might have more than one number ordered_non_unique< composite_key< phonebook_entry, member<phonebook_entry,std::string,&phonebook_entry::family_name>, member<phonebook_entry,std::string,&phonebook_entry::given_name> > >, ordered_unique< // unique as numbers belong to only one subscriber member<phonebook_entry,std::string,&phonebook_entry::phone_number> >
phonebook;
</raw>
the lines member<phonebook_entry,std::string,&phonebook_entry::family_name>, member<phonebook_entry,std::string,&phonebook_entry::given_name> should be auto-generated by reading a composite key from a file.
That use case sounds incompatible with composite keys, which must be defined at compile time. In that case, I would recommend creating individual indices on the container for each field that you might want to use at runtime, but you would lose the composite key functionality. Jason

syvyi <alexander.svk <at> gmail.com> writes:
What if the composite key should be parameterized from a file?
OK, this can be done, but you need to move some of the container definition components from compile time to run time. The following typedef std::function<boost::any(const person&)> any_person_extractor; defines a polymorhpic key extractor on person: something that takes a person and return something (which we wrap in a boost::any object, since we won't know what this something is until run time.) Similarly, typedef std::function< bool(const boost::any&,const boost::any&)> any_compare; is a polymorphic wraper for compare objects taking boost::any's: each compare objects we feed into any_compare will have to know what's inside these boost::any's to do the proper comparison, which we can do with template<typename T> struct any_less { bool operator()(const boost::any& x,const boost::any& y)const { return boost::any_cast<T>(x)<boost::any_cast<T>(y); } }; As composite_keys have to be defined with a predefined number of slots, we must have dummy extractors and compare objects to fill those up when the number of keys we specify at tun time is less than the number of slots: struct void_person_extractor { typedef boost::any result_type; result_type operator()(const person&)const{return boost::any();} }; template<> struct any_less<void> { bool operator()(const boost::any& x,const boost::any& y)const {return false;} }; Now, let's define the multi_index_container instantiation as: typedef multi_index_container< person, indexed_by< ordered_non_unique< composite_key< person, any_person_extractor, any_person_extractor, any_person_extractor, any_person_extractor >, composite_key_compare< any_compare, any_compare, any_compare, any_compare > >
person_container;
What we are doing here is reserve 4 slots (we can have more, of course) to fill at run time with specific key extractors (and their corresponding compare objects.) For instance, the following person_container c( boost::make_tuple( boost::make_tuple( boost::make_tuple( any_person_extractor(member<person,int,&person::birth_year>()), any_person_extractor(member<person,std::string,&person::name>()), any_person_extractor( member<person,std::string,&person::surname>()), void_person_extractor() ), boost::make_tuple( any_less<int>(), any_less<std::string>(), any_less<std::string>(), any_less<void>() ) ) )); instantiates a person_container with a composite key having three extractors on birth year, name and surname (a more elaborate example would fetch the info on which extractors toprovide from a configuration file or something); the remainng slot we fill with our dummy key extractor and compa object. Once instantiated, c can be used as a normal (compile-time defined) container. for instance, the following retrieves the persons born in 1959: std::pair<person_container::iterator,person_container::iterator> p= c.equal_range(1959); If the first key extractor weren't compatible with the int we've provided, for instance if we'd passed a string, a boost:any exception would be thrown --that's the price we pay for having this run-time flexibility, lack of compile time type checkhing. And that's it. You can play with a full example at http://coliru.stacked-crooked.com/a/4fa76b314298516d Joaquín M López Muñoz Telefónica Digital
participants (3)
-
Jason Roehm
-
Joaquin M Lopez Munoz
-
syvyi