c++upcasting

What is the fastest way to upcast std::shared_ptr<std::unique_ptr<T>>?


Suppose class D is derived from class B. What is the best way to convert a std::shared_ptr<std::unique_ptr<D>> to std::shared_ptr<std::unique_ptr<B>>? The solution should not increment / decrement the std::shared_ptr counter and should not make copy of the std::unique_ptr.

The naive approach does not work:

#include <memory>

struct B {
    virtual void msg() {
        printf("BASE\n");
    }

    virtual ~B() = default;
};

struct D: B {
    D() = default;

    void msg() override {
        printf("DERIVED\n");
    }
};


int main() {
    std::shared_ptr<std::unique_ptr<D>> derivedPtr = std::make_shared<std::unique_ptr<D>>(std::make_unique<D>());
    std::shared_ptr<std::unique_ptr<B>> basePtr = static_cast<std::shared_ptr<std::unique_ptr<B>>>(std::move(derivedPtr));
    basePtr->get()->msg();
}

The compiler says that this static_cast is impossible.


Solution

  • This is impossible (in any form) because std::unique_ptr<B> and std::unique_ptr<D> are not in any form related by inheritance.

    Conceptually this is wrong and this is also the first time I have seen a shared pointer holding a unique pointer. That itself seems like a big red flag on the whole approach and makes it sound like a XY problem.

    Why does the shared pointer hold the unique pointer instead of holding the object that the unique pointer holds directly?