$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
Subject: Re: [boost] [move] problem with msvc-10	(BOOST_MOVABLE_BUT_NOT_COPYABLE)
From: Jeffrey Lee Hellrung, Jr. (jhellrung_at_[hidden])
Date: 2010-11-25 01:57:31
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<oliver.kowalke_at_[hidden]>
>> An: boost_at_[hidden]
>>
>> 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