0

In all answers I have seen so far, it was either that someone was using shared_from_this() when there was indeed no shared pointer of the object, or the inheritance of enable_shared_from_this was private. That seems not to be the case here.

Do you see why it throws the exception?

The exception gets thrown in the instantiation (constructor) of the shared pointer for ShoeManager.

main()
{
    std::shared_ptr<IVRshoeDevice> leftShoe = InitDeviceConfiguration(leftConfiguration, "leftName");
    std::shared_ptr<IVRshoeDevice> rightShoe = InitDeviceConfiguration(rightConfiguration, "rightName");
    
    std::shared_ptr<ShoeManager> shoeManager = std::make_shared<ShoeManager>(leftShoe, rightShoe);

    return 0;
}

ShoeManager inherits from enable_shared_from_this

class ShoeManager : public std::enable_shared_from_this<ShoeManager>
    {
        public:
            ShoeManager(std::shared_ptr<IVRshoeDevice> shoe1, std::shared_ptr<IVRshoeDevice> shoe2);
}

The exception is thrown on this line.

ShoeManager::ShoeManager(std::shared_ptr<IVRshoeDevice> shoe1, std::shared_ptr<Freeaim::IVRshoeDevice> shoe2) 
{

    shoe1->SetManager(shared_from_this()); // < bad weak_ptr exception
    shoe2->SetManager(shared_from_this());
}

What I want is that both shoes know what they are managed by. In another language I would just do: shoe1->SetManager(this);, but with pointers in cpp that is not very safe. Any options?

Amber Elferink
  • 132
  • 1
  • 10
  • 1
    `shared_from_this` doesn't work in a constructor, the object hasn't finished being constructed and it hasn't been assigned to a `shared_ptr` yet. – François Andrieux Mar 17 '22 at 15:28
  • Thanks @FrançoisAndrieux, do you know another solution to make sure the Shoes always know they are assigned a ShoeManager (and can call to it)? It seems a bit silly to do separate calls for each shoe every time I create a ShoeManager – Amber Elferink Mar 17 '22 at 15:29
  • You can provide a factory function and make the constructor private. A factory function is a public `static` function that makes an instance and returns a smart pointer to that new instance. You then construct the instance in the factory function and then once it's constructed, you assign the shared_ptr to the manager instead of in the constructor. It's possible using this solution that you don't even need `enable_from_shared_this`. But in reality, if you have a manager, you might not need shared ownership. I'd make sure shared ownership is really what you need. – François Andrieux Mar 17 '22 at 15:41
  • Thanks for that, I might look into the factory function. I wanted to do it without shared ownership first and let the manager just hold both of the IVRshoes, however, I need to call a function in the Manager from a callback in the IVRshoe. So in my head, I need to be able to point to it to do that call. Maybe there is another solution that I did not think of? The factory seems like a possible solution – Amber Elferink Mar 17 '22 at 15:45
  • It's fine to use raw pointers or references to refer to an object, as long as it isn't used to manage lifetime. For example, if you know the callback will necessarily be fully resolved before the manager's lifetime ends, and that nobody will try to keep a copy of the pointer after the callback, then it's perfectly fine to use a raw pointer for that purpose. A common mistake when starting out with smart pointers is to assume it is always necessary to use them for everything. You only need them for owning pointers. – François Andrieux Mar 17 '22 at 16:01
  • Thanks @FrançoisAndrieux, in the end I solved the issue using raw pointers. (Then you can actually do this in the constructor, no factory required.) – Amber Elferink Mar 20 '22 at 23:55

0 Answers0