[move] problem with msvc-10 (BOOST_MOVABLE_BUT_NOT_COPYABLE)

-------- 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. ? 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; }

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 -- View this message in context: http://boost.2283326.n4.nabble.com/move-problem-with-msvc-10-BOOST-MOVABLE-B... Sent from the Boost - Dev mailing list archive at Nabble.com.

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@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) ); }
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

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 €/mtl.! Jetzt auch mit gratis Notebook-Flat! http://portal.gmx.net/de/go/dsl
participants (3)
-
Jeffrey Lee Hellrung, Jr.
-
Oliver Kowalke
-
Vicente Botet