Boost logo

Boost Users :

Subject: Re: [Boost-users] Using shared_ptr with reference_wrapper
From: Ovanes Markarian (om_boost_at_[hidden])
Date: 2012-01-19 17:42:31


Hi!

On Thu, Jan 19, 2012 at 9:15 PM, Kelvin Chung <kelvSYC_at_[hidden]> wrote:

> I am currently in the middle of a wrapper conundrum. I currently have the
> following:
>
> template <class Key, class Container>
> class ContainerWrapper {
> Container container;
> public:
> typedef Key key_type;
> protected:
> virtual const typename Container::key_type& mapKey(const key_type&)
> = 0;
> };
>
> The idea of ContainerWrapper is that I want to disguise one Key type as
> another key type. But the following wrapper, intended to present a
> container of Key pointers as a container of Keys, presents a dangling
> reference problem:
>
> template <class Key, class Container>
> class HeapKeyWrapper : public ContainerWrapper<Key, Container> {
> // Container::key_type == boost::shared_ptr<Key>
> public:
> typedef Key key_type;
> protected:
> // Ignore the lack of boost::const_pointer_cast<Key>**() below.
> The dangling reference is from the fact
> // that shared_from_this() doesn't return a reference.
> const boost::shared_ptr<Key>& mapKey(const key_type& key) { return
> key.shared_from_this(); }
> };
>
> If I try to fix this by having mapKey() return by value, then this other
> wrapper breaks:
>
> template <class Key, class Container>
> class IdentityWrapper : public ContainerWrapper<Key, Container> {
> public:
> typedef Key key_type;
> protected:
> // Assume Key extends boost::enable_shared_from_**this<Key>.
> // Returning by value would mean the returned value is a copy of
> key, and not the original
> // so calling shared_from_this() from the mapped key would break,
> say
> const Key& mapKey(const key_type& key) { return key; }
> };
>
> I'm trying to fix the code so that both wrappers work (short of
> refactoring the mapKey() functionality to a functor of some sort), which
> leads me thinking about using boost::reference_wrapper in some way. (The
> problem that I have is that I could have IdentityWrapper::mapKey() return a
> reference_wrapper, but that violates the mapKey() interface.)
>
> This has also led me down to a related path - what if I changed my backing
> container to use reference_wrapper instead of shared_ptr? It seems to be
> that it is ill-advised: the container technically isn't holding the object,
> and so the objects in the container could be deallocated in the meantime,
> leaving me with containers full of dangling references. I have valid uses
> of both HeapKeyWrapper and IdentityWrapper elsewhere in my code, so what do
> you think should be the right choice given this dangling reference problem
> currently present in HeapKeyWrapper?
>
>
if understood you right I would suggest using boost:weak_ptr, it can be
converted to shared_ptr if it still points to a valid object. shared_ptr
internally maintains the weak_ptr list.

It might also make sense to change your approach and start using boost
ptr_container:
http://www.boost.org/doc/libs/1_48_0/libs/ptr_container/doc/ptr_container.html

They were explicitly designed to work with heap allocated objects in
containers.

Hope that helps,

Ovanes



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