I have a class following this pattern:
class Foo { public:
All Foo objects are owned by Bar :
class Bar { public: ~Bar() { for(int i=0; i<foos_.size(); i++) delete foos_[i]; } private: vector<Foo*> foos_; };
Of course, this is a simplified example to get an idea. I have a guarantee that there is no loop from Foo s, and that the linked Foo all belongs to one instance of Bar . So far, so good. To do something in C ++ 11, I would use vector< unique_ptr<Foo> > foos_; to Bar and passed foos_[i].get() as a potential argument to the Foo constructor.
There is a deal:
This is a GUI application, and the user can interactively remove some Foo as desired. The expected behavior is that if foo1 is deleted, and foo2 refers to foo1 , then foo2 is now "absolute":
void Foo::convertToAbsolute() { a_ += other_->x(); other_ = 0; } void usageScenario() { Foo * foo1 = new Foo(42); Foo * foo2 = new Foo(foo1, 42);
I know that this can be done using source pointers, using the aa DAG structure with back pointers, so Foo knows who βdepends on themβ and can report it before deleting (possible solutions are described in detail here and here ).
My question is: will you handle it the same way? Is there a way to use C ++ 11 standard smart pointers to avoid explicit back pointers and then avoid calling areRelativeToMe_[i]->convertToAbsolute(); in the destructor Foo ? I was thinking of weak_ptr , something in the spirit:
class Foo { weak_ptr<Foo> other_; }; double Foo::x() const { if(other_.isExpired()) convertToAbsolute();
But the problem is that convertToAbsolute() needs a relative Foo that still exists. Therefore, I need a non-owning smart pointer that can say that "this link has logically expired", but actually extends the life of the object it refers to until it is needed.
This can be seen either as weak_ptr , which extends the lifetime, until it is shared with another weak_ptr :
class Foo { extended_weak_ptr<Foo> other_; }; double Foo::x() const { if(other_.isExpired()) { convertToAbsolute(); other_.reset();
Or like a shared_ptr with a different level of ownership:
class Bar { /* ... */ vector< multilevel_shared_ptr<Foo> foos_; }; class Foo { /* ... */ multilevel_shared_ptr<Foo> other_; }; void Bar::createFoos() { // Bar owns the Foo* with the highest level of ownership "Level1" // Creating an absolute Foo foos_.push_back( multilevel_unique_ptr<Foo>(new Foo(42), Level1) ); // Creating a relative Foo foos_.push_back( multilevel_unique_ptr<Foo>(new Foo(foos_[0],7), Level1) ); } Foo::Foo(const multilevel_unique_ptr<Foo> & other, int dx) : other_( other, Level2 ), // Foo owns the Foo* with the lowest level of ownership "Level2" a_(dx) { } double Foo::x() const { if(other_.noLevel1Owner()) // returns true if not shared // with any Level1 owner { convertToAbsolute(); other_.reset(); // now the object is destructed, unless // shared with other Level2 owners } // ... }
Any thoughts?