Преобразование из boost:: shared_ptr в std:: shared_ptr?
У меня есть библиотека, которая внутренне использует версию Boost shared_ptr
и предоставляет только те. Для моего приложения я хотел бы использовать std::shared_ptr
, когда это возможно. К сожалению, нет прямого преобразования между этими двумя типами, поскольку материал подсчета ссылок зависит от реализации.
Можно ли использовать оба объекта boost::shared_ptr
и std::shared_ptr
для одного объекта ref-count-object? Или, по крайней мере, украсть счетчик ссылок из версии Boost, и только пусть версия stdlib позаботится об этом?
Ответы
Ответ 1
Вы можете переносить boost:: 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>
.
Ответ 2
Сначала я ответил на ответ 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, T>(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, T>(p)) {
return h->p;
} else {
return boost::shared_ptr<T>(p.get(), Holder<std::shared_ptr<T>>(p));
}
}
Это решение не оставляет оснований для того, чтобы не использовать его без ограничений, поскольку вы возвращаете исходный указатель, если вы переводите обратно в исходный тип.