Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unique copy of std::shared_ptr

Tags:

c++

c++11

I have an object (let's call it X) that is accessible by other object by the means of std::shared_ptr. However at some point in the on of these objects need to create an unique, non-shared copy of X because it wants to modify it. This is somehow similar to copy-on-write, but not exactly the same due to some other details.

Basically I would like to have such semantics:

struct Foo
{
  std::shared_ptr<Bar> bar;
  void go()
  {
    // bar.use_count() >= 1
    bar.make_this_object_unique();
    // bar.use_count() == 1
  }
}
like image 584
Alex Watson Avatar asked Jan 10 '14 14:01

Alex Watson


2 Answers

If you simply want to copy the object, and get a shared pointer to the new object, then that's

bar = std::make_shared<Bar>(*bar);

This assumes that Bar is the actual type of the target. If you want to copy arbitrary subclasses of Bar, then you'll need a virtual function to copy the object, for example:

struct Bar {
    virtual std::shared_ptr<Bar> clone() = 0;
};

struct SomeKindOfBar : Bar {
    virtual std::shared_ptr<Bar> clone() {
        return std::make_shared<SomeKindOfBar>(*this);
    }
};

bar = bar->clone();

You might want to test bar.unique() to determine whether the copy is necessary.

like image 71
Mike Seymour Avatar answered Sep 29 '22 05:09

Mike Seymour


Not possible in the general case. May be possible in two cases:

  1. The object stored in bar is of Bar type and not of a class inherited from Bar. Then just use the copy constructor (provided it is available):

    bar = std::make_shared<Bar>(*bar);

  2. Bar or any of its base classes provides clone functionality in the form of virtual function creating newly allocated copy:

    bar = std::shared_ptr<Bar>(bar->Clone());

like image 44
Wojtek Surowka Avatar answered Sep 29 '22 03:09

Wojtek Surowka