Hi!

On Thu, Jan 19, 2012 at 9:15 PM, Kelvin Chung <kelvSYC@mac.com> 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