从boost::shared_ptr到std::shared_ptr的转换

Conversion from boost::shared_ptr to std::shared_ptr?

本文关键字:ptr shared 转换 std boost      更新时间:2023-10-16

我得到了一个库,它在内部使用Boost版本的shared_ptr,并且只公开这些。对于我的应用程序,我希望尽可能使用std::shared_ptr。遗憾的是,这两种类型之间没有直接转换,因为引用计数的内容取决于实现。

有没有办法让boost::shared_ptrstd::shared_ptr共享同一个引用计数对象?或者至少从Boost版本窃取ref计数,只让stdlib版本处理它?

基于janm最初的响应,我做了这个:

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(); });
}

但后来我意识到我可以这样做:

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));
    }
}

这个解决方案没有任何理由不受限制地使用它,因为如果转换回原始类型,就会返回原始指针。

更新到一个"离开我的头顶";答案,差不多11年后:

正如这个答案中所指出的,允许实现将deleter的生存期延长到shared_ptr的生存期之外。例如,直到所有weak_ptr实例也被销毁。这将导致weak_ptr实例的存在阻止底层对象的破坏,这显然是一个问题。

为了避免这种情况,可以在@Fozi的答案中使用方法,并显式调用reset(),也可以在链接答案中使用别名构造函数方法。

原始答案:

你可以携带助推::shared_ptr"内部";std::shared_ptr,使用析构函数携带引用:

template<typename T>
void do_release(typename boost::shared_ptr<T> const&, T*)
{
}
template<typename T>
typename std::shared_ptr<T> to_std(typename boost::shared_ptr<T> const& p)
{
    return
        std::shared_ptr<T>(
                p.get(),
                boost::bind(&do_release<T>, p, _1));
}

这样做的唯一真正原因是,如果您有一堆期望std::shared_ptr<T>的代码。