[multi_index] using boost::tuple and hash_unique
Hello, unfortunately I can't figure out how to specify member access for a hash function to a hash indexed mult-index container containing boost::tuple. I would like to hash by the first tuple member only. Can someone help? Here is an example: typedef boost::tuples::tuple<std::string, int, some_other_type> my_tuple; struct hash {}; multi_index_container< my_tuple , indexed_by< hashed_unique<tag<hash>, ???? , other_index_type... >
hashed_container;
I would like this tuple to be hashed by the first member. boost::tuple has no access member function to the first member. The only way to access it is: my_tuple t("aaa", 10, xyz); std::string s(get<0>(t)); but as I can see the doc for multi_index it supports only access through a member function or by using the hash function which is applied to the whole object. The second scenario does not suit well, since I must pass an object instance to the hasher, where I would like to pass a name only. Should I write my own key_extractor class? Any help is appreciated. With Kind Regards, Ovanes
Ovanes Markarian ha escrito:
Hello,
unfortunately I can't figure out how to specify member access for a hash function to a hash indexed mult-index container containing boost::tuple. I would like to hash by the first tuple member only. Can someone help?
Here is an example:
typedef boost::tuples::tuple<std::string, int, some_other_type> my_tuple;
struct hash {};
multi_index_container< my_tuple , indexed_by< hashed_unique<tag<hash>, ???? , other_index_type... >
hashed_container;
I would like this tuple to be hashed by the first member. boost::tuple has no access member function to the first member. The only way to access it is:
my_tuple t("aaa", 10, xyz);
std::string s(get<0>(t));
but as I can see the doc for multi_index it supports only access through a member function or by using the hash function which is applied to the whole object. The second scenario does not suit well, since I must pass an object instance to the hasher, where I would like to pass a name only. Should I write my own key_extractor class? Any help is appreciated.
Hello Ovanes, the issue of using a boost::tuple member as a key for a Boost.MultiIndex index has arisen in the past. Please read the following posts: http://lists.boost.org/boost-users/2005/12/16087.php http://lists.boost.org/boost-users/2005/12/16088.php Do they address your problem? Best regards, Joaquín M López Muñoz Telefónica, Investigación y Desarrollo
On Mon, April 23, 2007 18:27, Joaquín Mª López Muñoz wrote:
Hello Ovanes, the issue of using a boost::tuple member as a key for a Boost.MultiIndex index has arisen in the past. Please read the following posts:
http://lists.boost.org/boost-users/2005/12/16087.php http://lists.boost.org/boost-users/2005/12/16088.php
Do they address your problem? Best regards,
Joaquín M López Muñoz Telefónica, Investigación y Desarrollo
Thanks for the quick answer. If I correctly understand your answer, I will need either to use a custom key extractor, but then I can't make lookup by key like int or string, since I am forced to pass the whole tuple instance where the key is extracted. Is it true? Other solution would be to avoid using tuples... One more question, which might be offtopic. In my other scenario I use boost::hash to hash for string member of a pair, but the find fails if I pass a string const& and works if I pass const char*. Here an example: typedef std::pair<std::string, some_type const*> key_value_pair; struct hash {}; //tag used to retrieve values typedef mi::multi_index_container < key_value_pair , mi::indexed_by < mi::hashed_unique<mi::tag<hash>, BOOST_MULTI_INDEX_MEMBER(key_value_pair, std::string, first)> >
types_map;
This would fail: inline some_type_ptr create_type(std::string const& name)const { types_map::index<hash>::type::const_iterator i =types_.get<hash>().find(name); //... } But this works: inline some_type_ptr create_type(std::string const& name)const { types_map::index<hash>::type::const_iterator i =types_.get<hash>().find(name.c_str); ^^^^^^^^^^^^^^^^^ //... } Many thanks and With Kind Regards, Ovanes Markarian
Ovanes Markarian ha escrito:
On Mon, April 23, 2007 18:27, Joaquín Mª López Muñoz wrote:
Hello Ovanes, the issue of using a boost::tuple member as a key for a Boost.MultiIndex index has arisen in the past. Please read the following posts:
[...]
Thanks for the quick answer. If I correctly understand your answer, I will need either to use a custom key extractor, but then I can't make lookup by key like int or string, since I am forced to pass the whole tuple instance where the key is extracted. Is it true? Other solution would be to avoid using tuples...
No, no, if you use a custom key extractor like the tuple_member_extractor defined in one of the referred posts, you *can* use a string, an int or whatever the type of the tuple key member for doing lookup operations. This is what key extractors (predefine or custom) are for.
One more question, which might be offtopic. In my other scenario I use boost::hash to hash for string member of a pair, but the find fails if I pass a string const& and works if I pass const char*.
[...] I don't know what the problem is but it looks like there's more to it than you described. Please see the attached compilable snippet mimicking your scenario: it works OK for GCC 3.2, and it uses the string const& version of create_type(). Do you observe otherwise? When you say that the former fails: do you mean you get a compiler error? If so, what's it like?
Many thanks and
With Kind Regards,
Ovanes Markarian
Joaquín M López Muñoz Telefónica, Investigacion y Desarrollo
On Mon, April 23, 2007 19:34, Joaquín Mª López Muñoz wrote:
I don't know what the problem is but it looks like there's more to it than you described. Please see the attached compilable snippet mimicking your scenario: it works OK for GCC 3.2, and it uses the string const& version of create_type(). Do you observe otherwise? When you say that the former fails: do you mean you get a compiler error? If so, what's it like?
Well, what I mean is the following sample: #include <boost/array.hpp> #include <boost/multi_index_container.hpp> #include <boost/multi_index/hashed_index.hpp> #include <boost/multi_index/member.hpp> #include <utility> #include <string> #include <iostream> namespace mi=boost::multi_index; typedef int some_type; typedef std::pair<std::string, some_type const*> key_value_pair; //actually this is a predefined type boost::array<key_value_pair, 5> predefined_types = { key_value_pair("test1", NULL) , key_value_pair("test2", NULL) , key_value_pair("test3", NULL) , key_value_pair("test4", NULL) , key_value_pair("test5", NULL) }; struct hash{}; //tag used to retrieve values typedef mi::multi_index_container < key_value_pair, mi::indexed_by < mi::hashed_unique < mi::tag<hash>, BOOST_MULTI_INDEX_MEMBER(key_value_pair, std::string, first) >
types_map;
types_map types_(predefined_types.begin(), predefined_types.end()); inline void create_type(std::string const& name) { types_.insert(std::make_pair<std::string, some_type const*>(name, NULL)); } inline bool has_type(std::string const& name) { types_map::index<hash>::type::const_iterator i=types_.get<hash>().find(name), end = types_.get<hash>().end(); return i!=end; } int main() { //std::string s("hello"); //create_type(s); std::string s2("test3"); std::cout << "multi_index instance contains string \""+s2+"\": " << (has_type(s2)?"yes":"no"); } But in a clean environment it works fine and 'has_type' finds the string. May be I have some globally available identifier, which returns the wrong string, and therefore fails... I will double check it and get back to this post if I identify smth. Many thanks for your great support! With Kind Regards, Ovanes Markarian
participants (2)
-
Joaquín Mª López Muñoz
-
Ovanes Markarian