[move] Implicit conversion to rvalues and move ctors.
Here's another use case that fails to compile in C++03 but compiles successfully in C++11. (Note, it fails to compile in VS2005 and g++ 4.8.2 -std=c++98, and compiles successfully with g++ 4.8.2 -std=c++11) MOC is a BOOST_MOVABLE_BUT_NOT_COPYABLE type. Foo is an empty with an implicit conversion function to MOC. "MOC m(Foo());" compiles successfully but "MOC m2(makeFoo());" fails to compile. Is this a bug or a limitation of Boost.Move in C++03? //---------- //Start Code //---------- #include <boost/move/core.hpp> #include <boost/move/utility.hpp> struct MOC { MOC() : value(121) {} MOC(BOOST_RV_REF(MOC) rhs) : value(rhs.value) {} int value; private: BOOST_MOVABLE_BUT_NOT_COPYABLE(MOC) }; struct Foo { operator MOC () { return MOC(); } }; Foo makeFoo() { return Foo(); } int main() { // (1) Successfully Compiles. MOC m(Foo()); // (2) Fails to Compile. MOC m2(makeFoo()); return 0; } //-------- //End Code //-------- //-------------------- //Start Error Messages //-------------------- boost_move_implicit_conversion_to_rvalue.cc: In function ‘int main()’: boost_move_implicit_conversion_to_rvalue.cc:32:19: error: no matching function for call to ‘MOC::MOC(Foo)’ MOC m2(makeFoo()); ^ boost_move_implicit_conversion_to_rvalue.cc:32:19: note: candidates are: boost_move_implicit_conversion_to_rvalue.cc:10:3: note: MOC::MOC(MOC&) BOOST_MOVABLE_BUT_NOT_COPYABLE(MOC) ^ boost_move_implicit_conversion_to_rvalue.cc:10:3: note: no known conversion for argument 1 from ‘Foo’ to ‘MOC&’ boost_move_implicit_conversion_to_rvalue.cc:7:3: note: MOC::MOC(boost::rv<MOC>&) MOC(BOOST_RV_REF(MOC) rhs) : value(rhs.value) {} ^ boost_move_implicit_conversion_to_rvalue.cc:7:3: note: no known conversion for argument 1 from ‘Foo’ to ‘boost::rv<MOC>&’ boost_move_implicit_conversion_to_rvalue.cc:6:3: note: MOC::MOC() MOC() : value(121) {} ^ boost_move_implicit_conversion_to_rvalue.cc:6:3: note: candidate expects 0 arguments, 1 provided //------------------ //End Error Messages //------------------
Le 26/08/14 02:59, Mostafa a écrit :
Here's another use case that fails to compile in C++03 but compiles successfully in C++11. (Note, it fails to compile in VS2005 and g++ 4.8.2 -std=c++98, and compiles successfully with g++ 4.8.2 -std=c++11)
MOC is a BOOST_MOVABLE_BUT_NOT_COPYABLE type. Foo is an empty with an implicit conversion function to MOC. "MOC m(Foo());" compiles successfully but "MOC m2(makeFoo());" fails to compile. Is this a bug or a limitation of Boost.Move in C++03?
//---------- //Start Code //----------
#include <boost/move/core.hpp> #include <boost/move/utility.hpp>
struct MOC { MOC() : value(121) {} MOC(BOOST_RV_REF(MOC) rhs) : value(rhs.value) {} int value; private: BOOST_MOVABLE_BUT_NOT_COPYABLE(MOC) };
struct Foo { operator MOC () { return MOC(); } };
Foo makeFoo() { return Foo(); }
int main() { // (1) Successfully Compiles. MOC m(Foo());
// (2) Fails to Compile. MOC m2(makeFoo());
return 0; }
I'm getting ../example/lambda_future.cpp:32:8: warning: parentheses were disambiguated as a function declaration [-Wvexing-parse] MOC m(Foo()); ^~~~~~~ ../example/lambda_future.cpp:32:9: note: add a pair of parentheses to declare a variable MOC m(Foo()); ^ ( ) After adding the parentheses I get ../example/lambda_future.cpp:32:7: error: no matching constructor for initialization of 'MOC' MOC m((Foo())); ^ ~~~~~~~ In case this helps, Vicente
On Wed, 27 Aug 2014 16:17:06 -0700, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
Le 26/08/14 02:59, Mostafa a écrit :
Here's another use case that fails to compile in C++03 but compiles successfully in C++11. (Note, it fails to compile in VS2005 and g++ 4.8.2 -std=c++98, and compiles successfully with g++ 4.8.2 -std=c++11)
MOC is a BOOST_MOVABLE_BUT_NOT_COPYABLE type. Foo is an empty with an implicit conversion function to MOC. "MOC m(Foo());" compiles successfully but "MOC m2(makeFoo());" fails to compile. Is this a bug or a limitation of Boost.Move in C++03?
//---------- //Start Code //----------
#include <boost/move/core.hpp> #include <boost/move/utility.hpp>
struct MOC { MOC() : value(121) {} MOC(BOOST_RV_REF(MOC) rhs) : value(rhs.value) {} int value; private: BOOST_MOVABLE_BUT_NOT_COPYABLE(MOC) };
struct Foo { operator MOC () { return MOC(); } };
Foo makeFoo() { return Foo(); }
int main() { // (1) Successfully Compiles. MOC m(Foo());
// (2) Fails to Compile. MOC m2(makeFoo());
return 0; }
I'm getting
../example/lambda_future.cpp:32:8: warning: parentheses were disambiguated as a function declaration [-Wvexing-parse] MOC m(Foo()); ^~~~~~~ ../example/lambda_future.cpp:32:9: note: add a pair of parentheses to declare a variable MOC m(Foo()); ^ ( )
After adding the parentheses I get ../example/lambda_future.cpp:32:7: error: no matching constructor for initialization of 'MOC' MOC m((Foo())); ^ ~~~~~~~
Yes, you're right. That would explain the different compiler behaviors between (1) and (2). Adding double parenthesis to both (1) and (2) now gives me the same error messages in g++ 4.8.2 -std=c++98. But they both do compile under C++11 mode. FWIW, I have an internal workaround, I'm just wondering if this is another undocumented limitation of Boost.Move in C++98. (What's strange is that on my machine -Wall -pedantic doesn't even catch that MVPE you noted above.)
Le 28/08/14 01:49, Mostafa a écrit :
On Wed, 27 Aug 2014 16:17:06 -0700, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
Le 26/08/14 02:59, Mostafa a écrit :
Here's another use case that fails to compile in C++03 but compiles successfully in C++11. (Note, it fails to compile in VS2005 and g++ 4.8.2 -std=c++98, and compiles successfully with g++ 4.8.2 -std=c++11)
MOC is a BOOST_MOVABLE_BUT_NOT_COPYABLE type. Foo is an empty with an implicit conversion function to MOC. "MOC m(Foo());" compiles successfully but "MOC m2(makeFoo());" fails to compile. Is this a bug or a limitation of Boost.Move in C++03?
//---------- //Start Code //----------
#include <boost/move/core.hpp> #include <boost/move/utility.hpp>
struct MOC { MOC() : value(121) {} MOC(BOOST_RV_REF(MOC) rhs) : value(rhs.value) {} int value; private: BOOST_MOVABLE_BUT_NOT_COPYABLE(MOC) };
struct Foo { operator MOC () { return MOC(); } };
Foo makeFoo() { return Foo(); }
int main() { // (1) Successfully Compiles. MOC m(Foo());
// (2) Fails to Compile. MOC m2(makeFoo());
return 0; }
I'm getting
../example/lambda_future.cpp:32:8: warning: parentheses were disambiguated as a function declaration [-Wvexing-parse] MOC m(Foo()); ^~~~~~~ ../example/lambda_future.cpp:32:9: note: add a pair of parentheses to declare a variable MOC m(Foo()); ^ ( )
After adding the parentheses I get ../example/lambda_future.cpp:32:7: error: no matching constructor for initialization of 'MOC' MOC m((Foo())); ^ ~~~~~~~
Yes, you're right. That would explain the different compiler behaviors between (1) and (2). Adding double parenthesis to both (1) and (2) now gives me the same error messages in g++ 4.8.2 -std=c++98. But they both do compile under C++11 mode. FWIW, I have an internal workaround, I'm just wondering if this is another undocumented limitation of Boost.Move in C++98.
There is something specific to conversions and move semantics that seems to don't work. return an rvalue :( #include <boost/move/core.hpp> #include <boost/move/utility.hpp> struct Bar {}; struct MOC { MOC() : value(121) {} MOC(Bar) : value(122) {} MOC(BOOST_RV_REF(MOC) rhs) : value(rhs.value) {} int value; private: BOOST_MOVABLE_BUT_NOT_COPYABLE(MOC) }; struct Foo { operator MOC () const { return MOC(); } }; Foo makeFoo() { return Foo(); } Bar makeBar() { return Bar(); } MOC makeMOC() { return MOC(); } void f(MOC) {} void g(MOC&) {} void h(MOC const&) {} int main() { // (1) Fails to Compile.. //MOC m(Foo()); //MOC m((Foo())); // (1a) Compile. MOC m((Bar())); // (2) Fails to Compile. // MOC m2(makeFoo()); // (2a) Compiles. MOC m3(makeMOC()); MOC m4(makeBar()); // (3) Compiles. f(MOC()); // (3.a) Fails to Compile. //f(Bar()); //f(Foo()); // (4) Compiles. MOC x; g(x); // (4.a) Fails to Compile. //Bar y; //g(y); //Foo z; //g(z); // (5) Fails to Compile. //h(MOC()); // Normal is not MOC is not CopyConstructible // (5.a) Compiles. h(Bar()); // MOC is not Constructible from Bar h(Foo()); // // Foo is convertible to MOC return 0; }
(What's strange is that on my machine -Wall -pedantic doesn't even catch that MVPE you noted above.)
Here it is my cl "/Users/viboes/clang/clang+llvm-3.2-x86_64-apple-darwin11/bin/clang++" -x c++ -Wextra -Wno-long-long -Wunused-function -Wno-unused-value -Wno-c99-extensions -Wno-variadic-macros -O0 -g -O0 -fno-inline -Wall -g -DBOOST_ALL_NO_LIB=1 -DBOOST_CHRONO_STATIC_LINK=1 -DBOOST_SYSTEM_NO_DEPRECATED -DBOOST_SYSTEM_STATIC_LINK=1 -DBOOST_THREAD_BUILD_LIB=1 -DBOOST_THREAD_POSIX -DBOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED -DBOOST_THREAD_USE_LIB=1 -I"../../.." -c -o "../../../bin.v2/libs/thread/test/ex_lambda_future2_lib.test/clang-darwin-3.2/debug/threading-multi/lambda_future.o" "../example/lambda_future.cpp" Vicente
participants (2)
-
Mostafa
-
Vicente J. Botet Escriba