I'm wondering about how to (using C++11 and hopefully with backwards (boost or TR1) compatible smart pointer types) achieve:
One class instance (ModelController
) owns a resource (InputConsumer
), while another component (InputSender
, which in this case is a singleton) has access to it.
The model is InputSender
holds a list of references to InputConsumers
, of which there will be many.
ModelController
may have none, one, or many InputConsumers
, and there may be many ModelController
s. The InputSender
is NOT aware.
Here's what would be nice: A way for InputSender
to track the InputConsumers
assigned to it, in such a way that it can find out for itself whether the individual InputConsumers
are valid or not.
It seems to me that weak_ptr
is perfect for this purpose as their use requires checking this condition.
If InputSender
stops tracking any of its weak_ptr
refs, nothing bad happens, the corresponding InputConsumer
s will just experience radio silence.
If a ModelController
is deleted, or if a ModelController
deletes some of its InputConsumer
s, any InputSender
s that have registered with them will recognize at the next time they try to access them that they no longer exist, and can clean up, without the need to send a message or do anything.
So the question is, is this an appropriate situation for using shared_ptr
and weak_ptr
? I wonder if shared_ptr
is completely appropriate because the InputConsumer
s are conceptually owned by their ModelController
s, so they should be member variables. I dunno how much sense it makes for ModelController
to only manage them via shared_ptr
. I can't tell if unique_ptr
works together with weak_ptr
. Am I supposed to just manage the shared_ptr
s in ModelController
's ctor/dtor?
There may also be a well-known (not to me!) design pattern that this falls into, so if anyone knows of such a thing please tell me.
I do not have a lot of expertise in shared pointers, but yes, this seems a very appropriate use of
weak_ptr
.In this case, you are just annoyed that:
InputConsumer
s directly as members ofModelController
s, since its a trivial ownership relation.shared_ptr
to make it work with aweak_ptr
.I think this is solved by using a
shared_ptr
as an alias of a member object. According to C++.com:I never did it myself, but this seems adapted to your situation:
InputConsumer
s members ofModelController
sshared_ptr
for each of themInputSender
usingweak_ptr
sEDIT
Here is a complete minimal working example:
It prints:
The tricky part is to be able to create a
weak_ptr
toowner->foo1
(would be the same forfoo2
). To do that, we first need ashared_ptr
that is an alias ofowner->foo1
. This can only be done by:where
other_shared_ptr
is ashared_ptr<T>
whose lifetime is at least as long as the one ofowner->foo1
. To achieve this, using ashared_ptr<T>
which is also a member ofowner
is a good idea, since it ensures the lifetime would be the same. Finally, we need a valid non-null pointer to give to it, and since we don't want to create anything on the heap, we must use an existing object.this
is a good candidate, since we know it is valid and get destroyed only after its members are destroyed. Hence ourother_shared_ptr
is for instance:However, this means that when
self
gets out of scope, i.e. during the destruction ofowner
, it will calldelete this
. We do not want this deletion to occur, otherwisethis
would be deleted twice (which is undefined behaviour, in practice a segfault). Hence we also provide to the constructor ofself
a Deleter that actually doesn't delete anything.The rest of the code should be self-explanatory with the comments.