Search code examples
c++boostc++11shared-ptr

Error while copy constructing boost::shared_ptr using C++11


Yesterday I installed clang 3.1 and g++ 4.7 and tried compiling a project I'm working on. I was surprised to see that it didn't compile using both of the compilers. But what surprises me most is that the problem is in boost::shared_ptr.

Apparently, since that class defines a move constructor/assignment operator, the copy constructor is implicitly deleted. So this code:

#include <boost/shared_ptr.hpp>

int main() {
    boost::shared_ptr<int> x;
    boost::shared_ptr<int> y(x);
}

Does not compile. clang echoes this error:

test.cpp:5:28: error: call to implicitly-deleted copy constructor of
      'boost::shared_ptr<int>'
    boost::shared_ptr<int> y(x);
                           ^ ~
/usr/include/boost/smart_ptr/shared_ptr.hpp:347:5: note: copy constructor is
      implicitly deleted because 'shared_ptr<int>' has a user-declared move
      constructor
    shared_ptr( shared_ptr && r ): px( r.px ), pn() // never throws
    ^

g++ 4.7 provides a similar error, referring to the implicitly deleted constructor as well. The weird thing is that boost::shared_ptr, actually explicitly defines a copy constructor(boost/smart_ptr/shared_ptr.hpp line 228):

    template<class Y>
#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )

    shared_ptr( shared_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )

#else

    shared_ptr( shared_ptr<Y> const & r )

#endif
    : px( r.px ), pn( r.pn ) // never throws
    {
    }

I'm using boost 1.48.0.2, which is fairly new. Does anyone know what is going on in here? Why is the copy constructor not being detected when it's actually defined? Is this fixed in newer versions of the smart pointer library? I couldn't find anything on changelogs.


Solution

  • This is a known bug in Boost. The older versions (1.48 and lower) of Boost are not compilable under C++11, at least, not all. Personally, I use this workaround:

    #ifdef MY_LIB_COMPILING_UNDER_CXX11
    
    #include <memory>
    
    namespace my_lib {
    
    using std::shared_ptr;
    using std::weak_ptr;
    
    };
    
    #else
    
    #include <boost/shared_ptr.hpp>
    #include <boost/weak_ptr.hpp>
    
    namespace my_lib {
    
    using boost::shared_ptr;
    using boost::weak_ptr;
    
    };
    
    #endif
    

    Where MY_LIB_COMPILING_UNDER_CXX11 would be a flag that you set either passed to the compiler or deriving it from the compiler's C++11 flags. And, then, in the rest of the library I only use my_lib::shared_ptr. This works very well.