[Unordered] template find() request

Hello Boost, Suppose I have a boost::unordered_setstd::string. Now I want to find() a const char *, std::string, or even a string without zero termination (Google StringPiece). Converting these to std::string just to do a lookup is wasteful. Instead, I want to provide functors like: struct either_hash { size_t operator()(const std::string &str) const { return boost::hash_range(str.begin(), str.end()); } size_t operator()(const char *str) const { return boost::hash_range(str, str + std::strlen(str)); } }; This raises the question: what is either_hash::argument_type ? But it seems this is not used by boost::unordered_set . It should probably be std::string to match the underlying hash table. Would it make sense to change find() to template <class query_type> const_iterator find(const query_type& q) const ? For those familiar with Google StringPiece, one solution is using boost::unordered_set<StringPiece>, but then I have to keep the underlying strings somewhere outside the table. Further, a generalized find is useful in other cases, but this was the easiest to explain. Kenneth

Kenneth Heafield escribió:
Hello Boost,
Suppose I have a boost::unordered_setstd::string. Now I want to find() a const char *, std::string, or even a string without zero termination (Google StringPiece). Converting these to std::string just to do a lookup is wasteful. Instead, I want to provide functors like:
struct either_hash { size_t operator()(const std::string &str) const { return boost::hash_range(str.begin(), str.end()); }
size_t operator()(const char *str) const { return boost::hash_range(str, str + std::strlen(str)); } };
You'd also have to provide a polymorphic replacement for std::equal_tostd::string allowing interoperability between std::string's and const char *s.
This raises the question: what is either_hash::argument_type ? But it seems this is not used by boost::unordered_set . It should probably be std::string to match the underlying hash table.
Would it make sense to change find() to template <class query_type> const_iterator find(const query_type& q) const ?
FWIW, Boost.MultiIndex hashed indices do have a notion of "compatible keys" allowing for such heterogeneous lookup operations: http://www.boost.org/libs/multi_index/doc/tutorial/indices.html#hash_lookup http://www.boost.org/libs/multi_index/doc/reference/hash_indices.html#lookup Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

2009/3/9
This raises the question: what is either_hash::argument_type ? But it seems this is not used by boost::unordered_set . It should probably be std::string to match the underlying hash table. Would it make sense to change find() to template <class query_type> const_iterator find(const query_type& q) const ?
FWIW, Boost.MultiIndex hashed indices do have a notion of "compatible keys" allowing for such heterogeneous lookup operations:
http://www.boost.org/libs/multi_index/doc/tutorial/indices.html#hash_lookup http://www.boost.org/libs/multi_index/doc/reference/hash_indices.html#lookup
In the equivalent to this case: boost::unordered_setstd::string set; // .... set.find("x"); Is a std::string constructed for every hash and equality call? I can't see a way to avoid that without introducing a traits class. Daniel

Daniel James escribió:
2009/3/9
: FWIW, Boost.MultiIndex hashed indices do have a notion of "compatible keys" allowing for such heterogeneous lookup operations:
http://www.boost.org/libs/multi_index/doc/tutorial/indices.html#hash_lookup http://www.boost.org/libs/multi_index/doc/reference/hash_indices.html#lookup
In the equivalent to this case:
boost::unordered_setstd::string set;
// ....
set.find("x");
Is a std::string constructed for every hash and equality call? I can't see a way to avoid that without introducing a traits class.
Translating the compatible key functionality of B.MI to the syntax of boost::unordered_set, you'd have two ways of doing this: #1 struct custom_hash:boost::hashstd::string { using boost::hashstd::string::operator(); std::size_t operator()(const char* x)const { return boost::hash_range(x,x+std::strlen(x)); } }; struct custom_equal_to:std::equal_tostd::string { using std::equal_tostd::string::operator(); bool operator()(const std::string& x,const char* y)const { return x==y; } bool operator()(const char* x,const std::string& y)const { return x==y; } }; //... boost::unordered_setstd::string,custom_hash,custom_equal_to set; //... set.find("x"); #2 struct custom_hash { std::size_t operator()(const char* x)const { return boost::hash_range(x,x+std::strlen(x)); } }; struct custom_equal_to { bool operator()(const std::string& x,const char* y)const { return x==y; } bool operator()(const char* x,const std::string& y)const { return x==y; } }; //... boost::unordered_setstd::string set; //... set.find("x",custom_hash(),custom_equal_to()); Joaquín M López Muñoz Telefónica, Investigación y Desarrollo
participants (3)
-
Daniel James
-
joaquin@tid.es
-
Kenneth Heafield