[move] problem with msvc-10 (BOOST_MOVABLE_BUT_NOT_COPYABLE)

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

[move] problem with msvc-10 (BOOST_MOVABLE_BUT_NOT_COPYABLE)

Oliver Kowalke-2


-------- Original-Nachricht --------
Betreff: [move] problem with msvc-10 (BOOST_MOVABLE_BUT_NOT_COPYABLE)
Datum: Wed, 24 Nov 2010 20:56:46 +0100
Von: Oliver Kowalke <[hidden email]>
An: [hidden email]

Hi,
msvc-10 has some problems with boost.move.
linker error: LNK2019: unresolved symbol "private __cdecl X::X(class X
const&)"

Example doc_file_descriptor.cpp (uses BOOST_MOVABLE_BUT_NOT_COPYABLE)
does not compile too.

g++-4.4.5 accepts the code.

?

thx,
Oliver

#include <boost/move/move.hpp>
#include <boost/shared_ptr.hpp>

class X
{
private:
     BOOST_MOVABLE_BUT_NOT_COPYABLE( X);
     struct impl_t {};
     boost::shared_ptr< impl_t > impl_;
     X( boost::shared_ptr< impl_t > const& impl);
public:
     X();
     static X create();
     X( BOOST_RV_REF( X) other);
     X & operator=( BOOST_RV_REF( X) other);
        void swap( X & other);
};

X::X() : impl_()
{}

X::X( boost::shared_ptr< impl_t > const& impl) :
        impl_( impl)
{}

X X::create()
{
        boost::shared_ptr< impl_t > impl( new impl_t() );
        return X( impl);
}

X::X( BOOST_RV_REF( X) other) :
        impl_()
{ impl_.swap( other.impl_); }

X & X::operator=( BOOST_RV_REF( X) other)
{
        if ( this != & other)
        {
                X tmp( other);
                swap( tmp);
        }
        return * this;
}

void
X::swap( X & other)
{ impl_.swap( other.impl_); }

int main(int argc, char * argv[])
{
     X x( X::create() );
     return 0;
}
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [move] problem with msvc-10 (BOOST_MOVABLE_BUT_NOT_COPYABLE)

Vicente Botet
Oliver Kowalke-2 wrote

-------- Original-Nachricht --------
Betreff: [move] problem with msvc-10 (BOOST_MOVABLE_BUT_NOT_COPYABLE)
Datum: Wed, 24 Nov 2010 20:56:46 +0100
Von: Oliver Kowalke <oliver.kowalke@gmx.de>
An: boost@lists.boost.org

Hi,
msvc-10 has some problems with boost.move.
linker error: LNK2019: unresolved symbol "private __cdecl X::X(class X
const&)"

Example doc_file_descriptor.cpp (uses BOOST_MOVABLE_BUT_NOT_COPYABLE)
does not compile too.

g++-4.4.5 accepts the code.

?

X X::create()
{
        boost::shared_ptr< impl_t > impl( new impl_t() );
        return X( impl);
}
Shouldn't this function use boost::move?

X X::create()
{
        boost::shared_ptr< impl_t > impl( new impl_t() );
        return boost::move( X( impl) );
}

int main(int argc, char * argv[])
{
     X x( X::create() );
     return 0;
}
Shouldn't this declaration use boost::move?

     X x( boost::move(X::create()) );

Or shouldn't X::create returns a rvalue to X?

Best,
Vicente
Reply | Threaded
Open this post in threaded view
|

Re: [move] problem with msvc-10 (BOOST_MOVABLE_BUT_NOT_COPYABLE)

Jeffrey Lee Hellrung, Jr.
On 11/24/2010 10:33 PM, Vicente Botet wrote:

> Oliver Kowalke-2 wrote:
>> -------- Original-Nachricht --------
>> Betreff: [move] problem with msvc-10 (BOOST_MOVABLE_BUT_NOT_COPYABLE)
>> Datum: Wed, 24 Nov 2010 20:56:46 +0100
>> Von: Oliver Kowalke<[hidden email]>
>> An: [hidden email]
>>
>> Hi,
>> msvc-10 has some problems with boost.move.
>> linker error: LNK2019: unresolved symbol "private __cdecl X::X(class X
>> const&)"
>>
>> Example doc_file_descriptor.cpp (uses BOOST_MOVABLE_BUT_NOT_COPYABLE)
>> does not compile too.
>>
>> g++-4.4.5 accepts the code.
>>
>> ?
>>
>> X X::create()
>> {
>> boost::shared_ptr<  impl_t>  impl( new impl_t() );
>> return X( impl);
>> }
>>
>
> Shouldn't this function use boost::move?
>
> X X::create()
> {
> boost::shared_ptr<  impl_t>  impl( new impl_t() );
> return boost::move( X( impl) );
> }

I don't think that works in C++03 since boost::move takes its parameter
by reference-to-non-const; i.e., one should get a compiler error about
binding the temporary X to templated argument T& (I suppose MSVC might
let it slide since it allows such binding...).  It could work in C++0x,
depending on the declaration of boost::move, but it ultimately doesn't
change the semantics of the function (i.e., the move constructor, not
the copy constructor, will be invoked either way).

>> int main(int argc, char * argv[])
>> {
>>       X x( X::create() );
>>       return 0;
>> }
>>
>
> Shouldn't this declaration use boost::move?
>
>       X x( boost::move(X::create()) );

Same comments here.

> Or shouldn't X::create returns a rvalue to X?

You'd have to return a reference to a local, so that's a no go.  I think
the original X::create definition is correct.

Looking back at the original message, I think a problem is in the
definition of the move assignment operator:

BEFORE:
X & X::operator=( BOOST_RV_REF( X) other)
{
     if ( this != & other)
     {
         X tmp( other);
         swap( tmp);
     }
     return * this;
}

AFTER (corrected):
X & X::operator=( BOOST_RV_REF( X) other)
{
     if ( this != & other)
     {
         X tmp( boost::move(other) ); // must explicitly move other
         swap( tmp);
     }
     return * this;
}

The BEFORE code works in C++03 emulation mode since the expression
"other" actually is an emulated rvalue reference.  On the other hand, in
C++0x, the expression "other" is an lvalue reference, even though other
is declared as an rvalue reference, thus the BEFORE code actually uses
the copy constructor rather than the move constructor (and hence the
linker error).

The above behavior of the expression "other" is to help prevent
unintended moves.

I don't have access to MSVC10, so, Oliver, see if the above change gets
rid of the linker error.

- Jeff
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [move] problem with msvc-10 (BOOST_MOVABLE_BUT_NOT_COPYABLE)

Oliver Kowalke-2
In reply to this post by Vicente Botet
> Shouldn't this function use boost::move?
>
> X X::create()
> {
> boost::shared_ptr< impl_t > impl( new impl_t() );
> return boost::move( X( impl) );
> }

should work without move

> Shouldn't this declaration use boost::move?
>
>      X x( boost::move(X::create()) );
>
> Or shouldn't X::create returns a rvalue to X?

should work without move - returns an rvalue

BOOST_MOVABLE_BUT_NOT_COPYABLE provides operators returning rv< X >.

g++-4.4.5 accepts code above and afaik msvc-9.0 (on32bit windows) too.

Oliver
--
GMX DSL Doppel-Flat ab 19,99 &euro;/mtl.! Jetzt auch mit
gratis Notebook-Flat! http://portal.gmx.net/de/go/dsl
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost