composite key, want to use compatible key on part of it

Hi everybody, I have this boost::multi_index container (I'm very very happy with boost::multi_index!): typedef multi_index_container< CacheEntry, indexed_by < ordered_unique< composite_key< CacheEntry, member<CacheEntry,string,&CacheEntry::d_qname>, member<CacheEntry,uint16_t,&CacheEntry::d_qtype> >, composite_key_compare<CIStringCompare, std::less<uint16_t> > >, sequenced<> >
cache_t;
For details on CacheEntry, see http://wiki.powerdns.com/cgi-bin/trac.fcgi/browser/trunk/pdns/pdns/recursor_... What I want to do is use a compatible key ('char *') to search only on d_qname. I've tried: struct string_char_comp { bool operator()(const char* x, const tuple<string,uint16_t>& )const { return false; // bogus, just compile testing } bool operator()(const tuple<string,uint16_t>&, const char* x )const { return false; } }; Followed by: cache_t d_cache; // ... d_cachecache=d_cache.equal_range(qname.c_str(), string_char_comp()); But this doesn't compile with famously huge template errors (I've shortened boost::multi_index to bi::): ord_index_ops.hpp:87: error: no match for call to `(const string_char_comp) (bi::composite_key_result<bi::composite_key<MemRecursorCache::CacheEntry, bi::member<MemRecursorCache::CacheEntry, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, &MemRecursorCache::CacheEntry::d_qname>, bi::member<MemRecursorCache::CacheEntry, short unsigned int, &MemRecursorCache::CacheEntry::d_qtype>, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type> >, const char* const&)' These errors make me wonder if what I want is even possible - unless I make my comparison function accept a composite_key_result with lots of bi internals in it. Joaquin? -- http://www.PowerDNS.com Open source, database driven DNS Software http://netherlabs.nl Open and Closed source services

bert hubert ha escrito:
Hi everybody,
I have this boost::multi_index container (I'm very very happy with boost::multi_index!):
typedef multi_index_container< CacheEntry, indexed_by < ordered_unique< composite_key< CacheEntry, member<CacheEntry,string,&CacheEntry::d_qname>, member<CacheEntry,uint16_t,&CacheEntry::d_qtype> >, composite_key_compare<CIStringCompare, std::less<uint16_t> > >, sequenced<> >
cache_t;
For details on CacheEntry, see http://wiki.powerdns.com/cgi-bin/trac.fcgi/browser/trunk/pdns/pdns/recursor_...
What I want to do is use a compatible key ('char *') to search only on d_qname.
I've tried:
struct string_char_comp { bool operator()(const char* x, const tuple<string,uint16_t>& )const { return false; // bogus, just compile testing }
bool operator()(const tuple<string,uint16_t>&, const char* x )const { return false; } };
Followed by: cache_t d_cache; // ... d_cachecache=d_cache.equal_range(qname.c_str(), string_char_comp());
But this doesn't compile with famously huge template errors (I've shortened boost::multi_index to bi::):
[...]
These errors make me wonder if what I want is even possible - unless I make my comparison function accept a composite_key_result with lots of bi internals in it.
Joaquin?
Hello Bert, Your approach does not work because when string_char_comp::operator() is invoked internally, it is *not* passed a tuple, but an object of the opaque type composite_key_result<...> (http://tinyurl.com/yznxrj ). Moreover this composite_key_result thing is opaque in the sense that the user is not expected to mess much with it (read the reference for further details.) Fortunately, what you aim for can be done with a slightly different formulation: struct string_char_comp { bool operator()(const char* x, const std::string& )const { return false; // bogus, just compile testing } bool operator()(const std::string&, const char* x )const { return false; } }; ... d_cachecache=d_cache.equal_range( boost::make_tuple(qname.c_str()), // you can omit the make_tuple wrapper in Boost 1.34 composite_key_compare<string_char_comp>()); Note that the composite_key_compare instantiation only needs one comparison predicate, because you're passing one-element tuples. You can also have it combined with uint16_t's: d_cachecache=d_cache.equal_range( boost::make_tuple(qname.c_str(),105), // you cannot omit make_tuple here composite_key_compare<string_char_comp,std::less<uint16_t> >()); Hope this helps. Thanks for using Boost.MultiIndex in such exciting ways as you're doing in PowerDNS. Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

On Thu, Dec 14, 2006 at 07:13:03PM +0100, Joaqu?n M? L?pez Mu?oz wrote:
d_cachecache=d_cache.equal_range( boost::make_tuple(qname.c_str()), // you can omit the make_tuple wrapper in Boost 1.34 composite_key_compare<string_char_comp>());
Wonderful!
d_cachecache=d_cache.equal_range( boost::make_tuple(qname.c_str(),105), // you cannot omit make_tuple here composite_key_compare<string_char_comp,std::less<uint16_t> >());
The power of Boost.MultiIndex never ceases to amaze me Joaquin! In the end, I've solved the problem slightly differently, before your answer came in: typedef multi_index_container< CacheEntry, indexed_by < ordered_unique< composite_key< CacheEntry, member<CacheEntry,string,&CacheEntry::d_qname>, member<CacheEntry,uint16_t,&CacheEntry::d_qtype> >, composite_key_compare<CIStringCompare, std::less<uint16_t> > >, sequenced<> >
cache_t;
I've taught CIStringCompare that it can also compare const char*'s against std::strings, and things Just Worked - I tested it uses the char*/string comparisons now, and not the string/string comparison.
Hope this helps. Thanks for using Boost.MultiIndex in such exciting ways as you're doing in PowerDNS.
To a large extent, PowerDNS is just a frontend to Boost.MultiIndex. Also see: http://blog.netherlabs.nl/articles/2006/12/14/powerdns-speedups Thanks again Joaquin! -- http://www.PowerDNS.com Open source, database driven DNS Software http://netherlabs.nl Open and Closed source services
participants (2)
-
bert hubert
-
Joaquín Mª López Muñoz