I wrote a function template to "convert"/repack a boost::shared_ptr<T>
to a std::shared_ptr<T>
and vice versa by following this proposal. It's working fine unless I have a boost::shared_pt<T>
and the type of T
is an abstract class.
What I figured out so far is, that the problem occurs when boost/shared_ptr.hpp
and boost/shared_array.hpp
are included together. If only boost/shared_ptr.hpp
is included it's working when the type of T
is an abstract class.
I'm using clang 3.3 and boost 1.55.0 . It would be great if someone could tell my why it's not working and how to get it working.
Thanks for your help
Here is a minimal example:
//main.cpp
#include <boost/shared_array.hpp> //removing this include and it's working
#include <boost/shared_ptr.hpp>
#include <memory>
template<typename 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 () (...) const {}
};
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)) // get_deleter seems to cause the problem
{
return h->p;
}
else
{
return std::shared_ptr<T>(p.get(), Holder<boost::shared_ptr<T>>(p));
}
}
Here the code I used to test it:
//main.cpp
template<typename T> class Base
{
public:
T value;
virtual void abstract() = 0;
virtual ~Base() {}
};
template<typename T> class Derived : public Base<T>
{
public:
virtual void abstract() override {}
virtual ~Derived() {}
};
int main(int argc, const char * argv[])
{
boost::shared_ptr<Base<int>> ptr{new Derived<int>()};
// error here
std::shared_ptr<Base<int>> a = to_std_ptr(ptr);
// no error here
std::shared_ptr<Base<int>> b = to_std_ptr(boost::static_pointer_cast<Derived<int>>(ptr));
return 0;
}
Here's the error message(shortened):
boost/smart_ptr/shared_array.hpp:111:102: error: array of abstract class type 'Base<int>'
shared_array( shared_array<Y> const & r, typename boost::detail::sp_enable_if_convertible< Y[], T[] >::type = boost::detail::sp_empty() )
main.cpp:64:40: note: in instantiation of template class 'boost::shared_array<Base<int> >' requested here
if(H *h = boost::get_deleter<H, T>(p))
main.cpp:86:36: note: in instantiation of function template specialization 'to_std_ptr<Base<int> >'requested here
std::shared_ptr<Base<int>> i = to_std_ptr(ptr);
main.cpp:23:18: note: unimplemented pure virtual method 'abstract' in 'Base'
virtual void abstract() = 0;
What I get from the error message is that the compiler tried to create an array of abstract classes what of course doesn't work. But why is he even trying to do so and what has boost/sharred_array
to do with that. Is he maybe picking the wrong overload for boost::get_deleter
?