[multiindex] key extractor as free function - how?
Hi! I read from the docs that we can define key extractors to be one of - identity - member - mem_fun - composite_key Is it possible to use a free function as key extractor in the same way as the ones listed above and can you give an example of this? reagrds, Markus
Markus Werle ha escrito:
Hi!
I read from the docs that we can define key extractors to be one of - identity - member - mem_fun - composite_key
Is it possible to use a free function as key extractor in the same way as the ones listed above and can you give an example of this?
Hello Markus, There is no *predefined* key extractor designed for use with free functions, but you can easily write your own, as sketched in the following: struct element{...}; // free function to be used for key extraction int get_value(const element& x); // associated key extractor struct get_value_extractor { typedef int result_type; result_type operator()(const element& x)const { return get_value(x); } }; typedef multi_index_container< element, indexed_by< ordered_unique<get_value_extractor>, ...
multi_t;
User-defined key extractors are explained at http://tinyurl.com/l3g6u . On the other hand, it might be a good idea to provide an additional predefined key extractor for use with free functions so as to supplement the existing ones working with member functions, I'll add this to my to consider list. Hope this helps, Joaquín M López Muñoz Telefónica, Investigación y Desarrollo
Joaquín Mª López Muñoz <joaquin <at> tid.es> writes:
User-defined key extractors are explained at http://tinyurl.com/l3g6u .
[Easy archive reading at times when tinyurl vanished: Joaquín means http://boost-consulting.com/boost/libs/multi_index/ doc/tutorial/key_extraction.html#user_defined_key_extractors] I apologize for not reading the (really good) docs carefully enough. Thanks for your answer.
On the other hand, it might be a good idea to provide an additional predefined key extractor for use with free functions so as to supplement the existing ones working with member functions, I'll add this to my to consider list.
This would be fine. Markus
Joaquín Mª López Muñoz <joaquin <at> tid.es> writes:
[solution]
Unfortunately your solution does not work for tuples. The following code fails with a 10-page error message with gcc: #include <boost/tuple/tuple.hpp> #include <boost/multi_index_container.hpp> #include <boost/multi_index/sequenced_index.hpp> #include <boost/multi_index/key_extractors.hpp> namespace bm = ::boost::multi_index; template <int I> struct tuple_t_extractor { typedef std::string const & result_type; template <typename Tuple> result_type operator()(Tuple const & t) const { return boost::get<I>(t); // return t.get<I>(); // fails, too } }; class C { typedef boost::tuple<std::string, std::string> data_t; typedef bm::multi_index_container <data_t, bm::indexed_by <bm::sequenced<>, bm::ordered_unique<tuple_t_extractor<0> > > > storage_t; storage_t storage_; }; int main() { C c; }
Markus Werle <numerical.simulation <at> web.de> writes:
Joaquín Mª López Muñoz <joaquin <at> tid.es> writes:
[solution]
Unfortunately your solution does not work for tuples. The following code fails with a 10-page error message with gcc:
#include <boost/tuple/tuple.hpp> #include <boost/multi_index_container.hpp> #include <boost/multi_index/sequenced_index.hpp> #include <boost/multi_index/key_extractors.hpp>
template error messages are somewhat misleading ... finally caught it: #include <boost/multi_index/ordered_index.hpp> was missing Markus
Markus Werle ha escrito:
Markus Werle <numerical.simulation <at> web.de> writes:
JoaquÃn Mª López Muñoz <joaquin <at> tid.es> writes:
[solution]
Unfortunately your solution does not work for tuples. The following code fails with a 10-page error message with gcc:
#include <boost/tuple/tuple.hpp> #include <boost/multi_index_container.hpp> #include <boost/multi_index/sequenced_index.hpp> #include <boost/multi_index/key_extractors.hpp>
template error messages are somewhat misleading ... finally caught it: #include <boost/multi_index/ordered_index.hpp> was missing
Markus
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Additionally to this solution, I explain other options at my other post, Joaquín M López Muñoz Telefónica, Investigación y Desarrollo
On 1/23/07, Joaquín Mª López Muñoz <joaquin@tid.es> wrote:
it might be a good idea to provide an additional predefined key extractor for use with free functions so as to supplement the existing
ones working with member functions, I'll add this to my to consider list.
Hope this helps,
Joaquín M López Muñoz Telefónica, Investigación y Desarrollo
I'm currently experimenting with a rule of thumb where my extensible template classes are all written using policies, but the default for each policy is one that calls a free function. Sort of a best of both worlds approach - or at least that's what I'm hoping. For example, intrusive_ptr could be rewritten to take an AddRef policy, and the default could be to call intrusive_ptr_add_ref, etc: template <typename T> struct intrusive_ptr_default_add_ref_policy { static void add_ref(T * t) { intrusive_ptr_add_ref(t); } }; template <typename T, typename AddRefPolicy = intrusive_ptr_default_add_ref_policy> struct intrusive_ptr { intrusive_ptr(...) { ... AddRefPolicy::add_ref(t); } }; So user can implement intrusive_ptr_add_ref() OR implement a policy class. Might not be worthwhile for intrusive_ptr but it's an easy example. Probably makes more sense for templates where you might actually want different behaviours for a particular type, in different contexts. Much like passing in a predicate to std::map<>, yet the default is std::less, which is based on the type's intrinsic operator<(). Speaking of map<> and std::less(), I kind of wish they added one extra point of abstraction there - something like std::order() or map_order() or key_order(), that was allowed to be overridden. The idea being that some types can have a meaningful order() when used as a key, that is different than the meaningful operator<(). In my case it was a string class consisting of shared static strings - so that, used as a key, they could be quickly compared using the actual pointer to the shared memory, so operator<() would be implemented using that method; but used as a typical string, you might want to order them aphabetically, so operator<() should be a lexigraphical compare. And yes, I could just make sure my map<> took a custom predicate, but I'd rather the string class control that 'intrinsic', and not have to police future uses of the class when used as a key, to ensure the right predicate is used. The real answer probably is that std::map<> should call a free function, like, say, extract_key(T const & t), and then call the predicate on that, instead of on T. Hey, which gets us right back to where we started - multi-index DOES have key-extraction (making it better than std::map<> already), and the OP is asking for it to be a free function! Now if we could only get std::map<> to use it... Tony
participants (3)
-
Gottlob Frege
-
Joaquín Mª López Muñoz
-
Markus Werle