1

Will the reference count still work if storing std::weak_ptr with static_pointer_cast?

Here is a very simplifed example (note that the SmallBox and BigBox classes are almost exactly the same):

#define OWNER_SMALLBOX    1
#define OWNER_BIGBOX      2

class Object
{
    private:
        std::weak_ptr<void> owner;
        int ownerType;

    public:

        void doSomethingIfOwnerStillExist()
        {
            if(std::shared_ptr<void> ownerShared = owner.lock())
            {
                switch(ownerType)
                {
                    case OWNER_SMALLBOX:
                        std::shared_ptr<SmallBox> smallBox = std::static_pointer_cast<SmallBox>(ownerShared);
                    break;

                    case OWNER_BIGBOX:
                        std::shared_ptr<BigBox> bigBox = std::static_pointer_cast<BigBox>(ownerShared);
                    break;
                }//switch
            }
        }

        Object(std::shared_ptr<void> _owner, int _ownerType)
        {
            owner = _owner;
            ownerType = _ownerType;
        }
};

class SmallBox
{
    private:
        std::list< std::shared_ptr<Object> > objects;

    public:

        static void addObject(std::shared_ptr<SmallBox> _smallBox)
        {
            std::shared_ptr<void> owner = std::static_pointer_cast<void>(_smallBox);
            objects.push_back(std::make_shared<Object>(owner, OWNER_SMALL_BOX));
        }
};

class BigBox
{
    private:
        std::list< std::shared_ptr<Object> > objects;
    public:

        static void addObject(std::shared_ptr<BigBox> _bigBox)
        {
            std::shared_ptr<void> owner = std::static_pointer_cast<void>(_bigBox);
            objects.push_back(std::make_shared<Object>(owner, OWNER_BIGBOX));
        }
};

I know I can make the SmallBox and BigBox classes inherit from i.e. a GeneralBox class, and have the void type replaced with a GeneralBox type, but the weak_ptr can point to several other types aswell, making inheritance quite big and clumpsy.

I am curious if the shared_ptr still can keep track of the weak pointers converted to void.

  • I'd also suggest using something like `std::variant, std::weak_ptr>` instead, if you really need to cast back to the original type in `doSomethingIfOwnerStillExist`, because it will manage all the `ownerType` tracking that you do for you automatically. Or better, as you mentioned, use a base class with the interface that `doSomethingIfOwnerStillExist` will use. Since you have to track every possible type in `Object` already anyway, I don't see how adding the interface to each of the classes instead would be more complex. – walnut Nov 23 '19 at 15:15
  • I will look up std::variant. I am sorry I could not reduce the example, I will see what I can do. – Johannes Bergmark Nov 23 '19 at 16:11

1 Answers1

3

If I understand your question correctly, then you are asking whether std::static_pointer_cast will return a std::shared_ptr sharing ownership with the argument that it is called on.

The answer to this is yes.

owner in addObject will share ownership with addObject's function parameter and owner in object will refer to the same control block, as will ownerShared and smallBox, bigBox in doSomethingIfOwnerStillExist.

Note however that the shared_ptr's that are stored in objects are completely unrelated, because they are initialized with calls to std::make_shared creating a new Objects that will be owned only by objects.

The std::static_pointer_cast would be pretty useless if it didn't return an instance sharing ownership with the argument, because it would inevitable lead to a double delete of the managed pointer, if it wasn't.

walnut
  • 21,629
  • 4
  • 23
  • 59
  • Thanks for your answer. I forgot to add the created object to the list in the example. It will be stored in the 'Box' classes. – Johannes Bergmark Nov 23 '19 at 16:10
  • Note that these pseudo "casts" are particular cases of the creation of an aliasing `shared_ptr` via the "aliasing constructor". You can even have an owning smart ptr to a member subobject, or an array element, or any object owned by object "co-owned" by the `shared_ptr`. – curiousguy Dec 04 '19 at 22:12