Boost logo

Boost Users :

From: Pavel Vazharov (freakpv_at_[hidden])
Date: 2022-11-03 07:06:37


On Wed, Nov 2, 2022 at 10:05 PM Joaquin M López Muñoz <
joaquinlopezmunoz_at_[hidden]> wrote:

> Insert+modify works fine as far as I can see:
> (http://coliru.stacked-crooked.com/a/eb5dc2b569dff95e )
>
> // C++20, easily portable to older C++ versions
>
> #include <boost/multi_index_container.hpp>
> #include <boost/multi_index/hashed_index.hpp>
> #include <boost/multi_index/key.hpp>
> #include <cassert>
> #include <string>
> #include <utility>
>
> using namespace boost::multi_index;
>
> struct element
> {
> int id;
> std::string str;
> };
>
> using container=multi_index_container<
> element,
> indexed_by<
> hashed_unique<key<&element::id>>
> >
> >;
>
> template<typename Index,typename Str>
> auto lazy_emplace(Index& i,int id,Str&& str)
> {
> auto p=i.emplace(id,std::string{});
> const auto& [it,b]=p;
> if(p.second)i.modify(it,[&](auto&
> e){e.str=std::forward<Str>(str);});
> return p;
> }
>
> int main()
> {
> container c={{0,"hello"}};
> std::string str="boost";
>
> auto [it,b]=lazy_emplace(c,0,std::move(str));
> assert(b==false&&!str.empty());
>
> std::tie(it,b)=lazy_emplace(c,1,std::move(str));
> assert(b==true&&str.empty());
> }
>
> Your particular problem hints at the more general issue that
> Boost.MultiIndex indices do not have
> something like try_emplace, which is the semantics you're after. The
> reason why this function
> is not available is that we have set-like indices, not map-like indices.
> For instance, this expression
>
> c.try_emplace(0,"hello");
>
> assumes that value_type is constructible from 0 and "hello" *and* that 0
> is the key. With
> Boost.MultiIndex, this assumption does not hold true in general, as the
> key is gotten via a key
> extractor and there's no mapping between construction args and keys or
> anything. That said,
> the following could be a potentially interesting addition to the library:
>
> template<typename Key,typename... Args>
> c.try_emplace(const Key& k,Args&&... args);
>
> where the value is constructed from args... and not from (k,args...),
> so, going back to your
> example, the syntax would be:
>
> s.try_emplace(0,0,"hello"); // first 0 is the key, (0,"hello")
> constructs element
>
> I have to think about this.
>
> Best,
>
> Joaquín M López Muñoz
>

Hi,

Thanks for the response.

Yes, you are right, I'm looking for an API with semantics like try_emplace
and now
I understand the complications for it for the case of boost multi_index.

I'm currently using emplace + modify API. My initial question was not very
clear about this.
However, my understanding is that the modify call will try to reposition
the node because
it can't be sure if the user callback hasn't changed something in the
entry which would
require repositioning of the node in any of the indices.
Is my understanding of the modify API correct?
As I'm using hashed + sequenced indices, I know that setting only the
mapped_type
in the modify call won't cause any repositioning in the both of the above
indices.
Thus I was trying to avoid the additional work which happens internally in
the modify call.

BTW, thanks for working on boost::unordered_flat_map because it'll allow us
to remove
3rd party dependency from our projects as we are currently using
https://greg7mdp.github.io/parallel-hashmap/.

Regards,
Pavel.



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net