multi_index, best way to do insert_or_replace

Hi, I misread (or didn't read) the boost::multi_index_container documentation and assumed 'insert' on a unique index would do 'replace', but of course it doesn't and shouldn't. So, I've made this change: - s_negcache.insert(ne); + + pair<negcache_t::iterator, bool> res=s_negcache.insert(ne); + if(!res.second) { + s_negcache.erase(res.first); + s_negcache.insert(ne); + } But I can't help feeling there is probably a better and prettier way. Do people have any suggestions? In this case, ne is a NegCacheEntry, defined as: struct NegCacheEntry { string d_name; QType d_qtype; string d_qname; uint32_t d_ttd; }; And the index: typedef multi_index_container < NegCacheEntry, indexed_by < ordered_unique< composite_key< NegCacheEntry, member<NegCacheEntry, string, &NegCacheEntry::d_name>, member<NegCacheEntry, QType, &NegCacheEntry::d_qtype> >, composite_key_compare<CIStringCompare, std::less<QType> > >, ordered_non_unique< member<NegCacheEntry, uint32_t, &NegCacheEntry::d_ttd> >
negcache_t;
Thanks! -- http://www.PowerDNS.com Open source, database driven DNS Software http://netherlabs.nl Open and Closed source services

bert hubert ha escrito:
Hi,
I misread (or didn't read) the boost::multi_index_container documentation and assumed 'insert' on a unique index would do 'replace', but of course it doesn't and shouldn't.
So, I've made this change:
- s_negcache.insert(ne); + + pair<negcache_t::iterator, bool> res=s_negcache.insert(ne); + if(!res.second) { + s_negcache.erase(res.first); + s_negcache.insert(ne); + }
But I can't help feeling there is probably a better and prettier way. Do people have any suggestions?
Hello Bert, You can do it more efficiently by using replace() instead of deleting and reinserting on collision. The following packages the entire procedure template<typename Index> std::pair<typename Index::iterator,bool> replacing_insert(Index& i,const typename Index::value_type& x) { std::pair<typename Index::iterator,bool> res=i.insert(x); if(!res.second)res.second=i.replace(res.first,x); return res; } So that you can say pair<negcache_t::iterator, bool> res=replacing_insert(s_negcache,ne); Note that replacing_insert() still cannot guarantee in the general case that insertion will always be succesful (hence its returning a pair<iterator,bool>): failure happens if two or more distinct elements are colliding with the value to be inserted. Check the attached code for an example of a failing call to replacing_insert(). HTH, Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

On Fri, Apr 28, 2006 at 10:22:49AM +0200, Joaqu?n M? L?pez Mu?oz wrote:
pair<negcache_t::iterator, bool> res=replacing_insert(s_negcache,ne);
Works, thank you (again) Joaquin! See http://wiki.powerdns.com/projects/trac/changeset/785
Note that replacing_insert() still cannot guarantee in the general case that insertion will always be succesful (hence its returning a pair<iterator,bool>):
Indeed - but in this case I know there is only one unique index, so I don't check. Thanks! -- 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