c++ - Is this approach of moving data from standard containers to shared pointers correct? -
here problem: have std::string defined in function. need extend scope of string because of asynchronous operation. naturally can copy shared pointer this:
{ std::string hi{"hi"}; auto shared_hi = std::make_shared<std::string>(hi); //insert shared_hi in async queue }
the problem strings very big, , vectors, , std::arrays. not avoid copy, have function can "steal" data out of containers without having copy them. i've come clever solution posted below, i'm wondering if there isn't better solution this. if there isn't, i'd know if doing i'm doing below defined behavior:
template<class t> class wrappeddeleter { public: wrappeddeleter(t &&other): o_(std::move(other)) { } private: t o_; }; //this function creates deleter scope template<class p, class t> std::function<void(p *)> make_delete(t &&encapsulate) { wrappeddeleter<t> *d = new wrappeddeleter<t>(std::move(encapsulate)); return [d](p * ptr) { std::cout << "deleting now\n"; delete d; }; } template<class p, class c> std::shared_ptr<p> steal_data(c &&data) { p *ptr = data.data(); //can't use make_shared - custom deleter return std::shared_ptr<p>(ptr, make_delete<p, c>(std::move(data))); }
used this:
int main() { { std::shared_ptr<int> p_a; std::shared_ptr<int> p_b; std::shared_ptr<const char> p_c; { std::array<int,3> a= {{1,2,3}}; std::vector<int> b= {1,2,3}; std::string c= {"hello world"}; p_a = steal_data<int,std::array<int,3> >(std::move(a)); p_b = steal_data<int, std::vector<int> >(std::move(b)); p_c = steal_data<const char, std::string>(std::move(c)); std::cout << "inside" << *p_a << " " << *p_b << " " << p_c.get() << std::endl; } std::cout << "outside" << *p_a << " " << *p_b << " " << p_c.get() << std::endl; std::cout << "end of scope\n"; } return 0; }
as praetorian says, sensible way move data shared_ptr
using make_shared<t>(move(obj))
. if want shared_ptr
point underlying contiguous data block rather container itself, can use alias constructor template<class y> shared_ptr(const shared_ptr<y>& r, t *ptr);
:
std::vector<int> v{1, 2, 3}; auto cptr = std::make_shared<std::vector<int>>(std::move(v)); std::shared_ptr<int> ptr{cptr, cptr->data()};
as function:
template<typename container> std::shared_ptr<container::value_type> steal_data(container &&cont) { auto cptr = std::make_shared<container>(std::move(cont)); return {cptr, cptr->data()}; }
Comments
Post a Comment