C++ – Conversion from boost::shared_ptr to std::shared_ptr

boostcshared-ptrstd

I got a library that internally uses Boost's version of shared_ptr and exposes only those. For my application, I'd like to use std::shared_ptr whenever possible though. Sadly, there is no direct conversion between the two types, as the ref counting stuff is implementation dependent.

Is there any way to have both a boost::shared_ptr and a std::shared_ptr share the same ref-count-object? Or at least steal the ref-count from the Boost version and only let the stdlib version take care of it?

Best Answer

Based on janm's response at first I did this:

template<class T> std::shared_ptr<T> to_std(const boost::shared_ptr<T> &p) {
    return std::shared_ptr<T>(p.get(), [p](...) mutable { p.reset(); });
}

template<class T> boost::shared_ptr<T> to_boost(const std::shared_ptr<T> &p) {
    return boost::shared_ptr<T>(p.get(), [p](...) mutable { p.reset(); });
}

But then I realized I could do this instead:

namespace {
    template<class SharedPointer> struct Holder {
        SharedPointer p;

        Holder(const SharedPointer &p) : p(p) {}
        Holder(const Holder &other) : p(other.p) {}
        Holder(Holder &&other) : p(std::move(other.p)) {}

        void operator () (...) { p.reset(); }
    };
}

template<class T> std::shared_ptr<T> to_std_ptr(const boost::shared_ptr<T> &p) {
    typedef Holder<std::shared_ptr<T>> H;
    if(H *h = boost::get_deleter<H>(p)) {
        return h->p;
    } else {
        return std::shared_ptr<T>(p.get(), Holder<boost::shared_ptr<T>>(p));
    }
}

template<class T> boost::shared_ptr<T> to_boost_ptr(const std::shared_ptr<T> &p){
    typedef Holder<boost::shared_ptr<T>> H;
    if(H * h = std::get_deleter<H>(p)) {
        return h->p;
    } else {
        return boost::shared_ptr<T>(p.get(), Holder<std::shared_ptr<T>>(p));
    }
}

This solution leaves no reason for not using it without restrictions since you get the original pointer back if you convert back to the original type.