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?
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.