Search code examples
c++visual-studio-2010boostmove

vs2010 build error with BOOST_MOVABLE_BUT_NOT_COPYABLE


The following is the simplified code:

--------------class foo-----------------------

class foo : private boost::noncopyable      //--- mark 1---
{
    BOOST_MOVABLE_BUT_NOT_COPYABLE(foo)     //--- mark 2---

public:

    /**
     * Move constructor.
     */
    foo(BOOST_RV_REF(foo) other);

    /**
     * Move-assignment.
     */
    foo& operator=(BOOST_RV_REF(foo) other);

    /**
     * Releases
     */
    ~foo();
    ......
private:
    fool_impl*  m_pimpl;
}

foo::foo(foo_impl* pimpl)
:m_pimpl(pimpl) 
{}

foo::foo(
    BOOST_RV_REF(foo) other) : m_pimpl(other.m_pimpl)
{
    other.m_pimpl = NULL;
}

foo& foo::operator=(
    BOOST_RV_REF(foo) other)
{
    if (&other != this)
    {
        delete m_pimpl;
        m_pimpl = other.m_pimpl;
        other.m_pimpl = NULL;
    }

    return *this;
}

foo::~foo()
{
    delete m_pimpl;
}

---------------class bar-----------

class bar
{
public:

    explicit bar(BOOST_RV_REF(foo) other);

    ......

private:

    foo m_foo;
};

bar::bar(BOOST_RV_REF(foo) other)
:
m_foo(other)                        //--- mark 3----
{}

when build with VS2010, mark 3 reports errors:

error C2248: 'foo' : cannot access private member declared in class 'foo'
1>   mark 1:  see declaration of 'foo'
1>   mark 2:  see declaration of 'foo'

I tried to modified some code, but useless. Can anyone give any advice? Thanks.


@Piotr S. Thanks for your answer, I tried, the error disappeared, but another error appeared:

class test
{
public:

    explicit test(
        BOOST_RV_REF(foo) other);

private:
    boost::shared_ptr<aClass> m_class;
};

test::test(BOOST_RV_REF(foo) other)
{
    m_class = boost::make_shared<aClass>(boost::ref(other));
}

error LNK2019: unresolved external symbol "private: __cdecl foo(class foo const &)" referenced in function "class boost::shared_ptr __cdecl boost::make_shared const >(class boost::reference_wrapper const &&)"

can you give any advice? Thanks!


Solution

  • You need to use boost::move():

    bar::bar(BOOST_RV_REF(foo) other)
    :
        m_foo(boost::move(other)) // move it !
    {}
    

    otherwise, the compiler is trying to access copy constructor foo(const foo&), which is inaccessible as this type is noncopyable. boost::move casts the value back to r-value reference (or whatever is hidden behind BOOST_RV_REF(foo) that emulates r-value references in C++03), making the proper call to foo(BOOST_RV_REF(foo) other).