web-dev-qa-db-ja.com

boost :: shared_ptrからstd :: shared_ptrへの変換?

Boostのバージョンのshared_ptrを内部的に使用し、それらのみを公開するライブラリを入手しました。私のアプリケーションでは、可能な限りstd::shared_ptrを使用したいと思います。残念ながら、参照カウントは実装に依存するため、2つのタイプ間で直接変換することはできません。

boost::shared_ptrstd::shared_ptrの両方に同じref-count-objectを共有させる方法はありますか?または、少なくともBoostバージョンからref-countを盗み、stdlibバージョンのみに処理させますか?

40
Xeo

デストラクタを使用して参照を持ち運ぶことにより、std :: shared_ptrの「内部」にboost :: 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>を期待するコードがたくさんある場合です。

30
janm

最初の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));
    }
}

このソリューションでは、元のタイプに変換して戻すと元のポインターが返されるため、制限なしで使用しない理由はありません。

36
Fozi