[move] differences between results in C++03 and C++11 modes
Hi! Some time ago I encountered a problem with assigning the return value of boost::move() to a non-const reference in C++11 mode, but not in C++03 mode. See [1] for a StackOverflow question that I created for this issue. It contains all the details so for brevity I won't repeat them here. Could anyone explain this issue? Is this a limitation of C++03 emulation or a defect in the implementation? Best regards, Adam Romanek [1] http://stackoverflow.com/questions/21138869/why-does-assigning-the-return-va...
El 11/02/2014 8:55, Adam Romanek escribió:
Hi!
Some time ago I encountered a problem with assigning the return value of boost::move() to a non-const reference in C++11 mode, but not in C++03 mode. See [1] for a StackOverflow question that I created for this issue. It contains all the details so for brevity I won't repeat them here. Could anyone explain this issue? Is this a limitation of C++03 emulation or a defect in the implementation?
Yes, it's a limitation of boost move. When called with the emulation code boost::move() returns a type rv<T> & that is convertible to T (and that is the key point to implement emulated move semantics). However in C++11 you return a T&& (unnamed rvalue reference) which is not assignable to T &. In your case, as R is std::ostream &, the emulation return rvstd::ostrean (convertible to std::ostream &) and the C++11 version returns std::ostream &&, which is not convertible to std::ostream &. I guess we could add a new macro to boost move for return types. In emulated mode, it moves the return value, In C++11 mode it only return the value (If RVO can't be applied the compiler will do an implicit move). Something like: //return boost::move(r) in emulation //return r in C++11 return BOOST_MOVE_RET(r); If you think it's a good idea, please fill a ticket. Best, Ion
2014-02-11 14:11 GMT+01:00 Ion Gaztañaga
El 11/02/2014 8:55, Adam Romanek escribió:
Hi!
Some time ago I encountered a problem with assigning the return value of boost::move() to a non-const reference in C++11 mode, but not in C++03 mode. See [1] for a StackOverflow question that I created for this issue. It contains all the details so for brevity I won't repeat them here. Could anyone explain this issue? Is this a limitation of C++03 emulation or a defect in the implementation?
Yes, it's a limitation of boost move. When called with the emulation code boost::move() returns a type rv<T> & that is convertible to T (and that is the key point to implement emulated move semantics). However in C++11 you return a T&& (unnamed rvalue reference) which is not assignable to T &.
In your case, as R is std::ostream &, the emulation return rvstd::ostrean (convertible to std::ostream &) and the C++11 version returns std::ostream &&, which is not convertible to std::ostream &.
I guess we could add a new macro to boost move for return types. In emulated mode, it moves the return value, In C++11 mode it only return the value (If RVO can't be applied the compiler will do an implicit move). Something like:
//return boost::move(r) in emulation //return r in C++11 return BOOST_MOVE_RET(r);
+1 I've written and use such a macro myself. Regards, Kris
On Tue, Feb 11, 2014 at 9:14 AM, Krzysztof Czainski <1czajnik@gmail.com>wrote:
2014-02-11 14:11 GMT+01:00 Ion Gaztañaga
: El 11/02/2014 8:55, Adam Romanek escribió:
Hi!
Some time ago I encountered a problem with assigning the return value of boost::move() to a non-const reference in C++11 mode, but not in C++03 mode. See [1] for a StackOverflow question that I created for this issue. It contains all the details so for brevity I won't repeat them here. Could anyone explain this issue? Is this a limitation of C++03 emulation or a defect in the implementation?
Yes, it's a limitation of boost move. When called with the emulation code boost::move() returns a type rv<T> & that is convertible to T (and that is the key point to implement emulated move semantics). However in C++11 you return a T&& (unnamed rvalue reference) which is not assignable to T &.
In your case, as R is std::ostream &, the emulation return rvstd::ostrean (convertible to std::ostream &) and the C++11 version returns std::ostream &&, which is not convertible to std::ostream &.
I guess we could add a new macro to boost move for return types. In emulated mode, it moves the return value, In C++11 mode it only return the value (If RVO can't be applied the compiler will do an implicit move). Something like:
//return boost::move(r) in emulation //return r in C++11 return BOOST_MOVE_RET(r);
+1 I've written and use such a macro myself. Regards, Kris
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
I recently wanted to write such a macro too. Objects marked with BOOST_MOVABLE_BUT_NOT_COPYABLE have to be returned with "return boost::move(temp)" or C++03 compilers try to use the private copy-constructor on temp. Doing a boost::move return prevents NRVO in C++03, and C++11 (according to the language purists and gcc 4.7.3). This macro would at least provide NRVO capabilities in C++11. I think C++03 support for NRVO in this situation is foolish; boost::move would have to invoke a private copy-constructor on the user type and hope the compiler didn't generate a function call to it. The documentation doesn't list these limitations AFAIK. Lee
El 12/02/2014 2:34, Lee Clagett escribió:
I recently wanted to write such a macro too. Objects marked with BOOST_MOVABLE_BUT_NOT_COPYABLE have to be returned with "return boost::move(temp)" or C++03 compilers try to use the private copy-constructor on temp. Doing a boost::move return prevents NRVO in C++03, and C++11 (according to the language purists and gcc 4.7.3). This macro would at least provide NRVO capabilities in C++11. I think C++03 support for NRVO in this situation is foolish; boost::move would have to invoke a private copy-constructor on the user type and hope the compiler didn't generate a function call to it. The documentation doesn't list these limitations AFAIK.
I've committed a first implementation to the develop branch: SHA-1: 062000ed68cecf59f29b99f5a6167529ea359979 * Added BOOST_MOVE_RET [develop 062000e] Added BOOST_MOVE_RET 7 files changed, 496 insertions(+), 129 deletions(-) create mode 100644 example/doc_move_return.cpp create mode 100644 proj/vc7ide/doc_move_return.vcproj Documentation is updated with the details. I also discovered that Visual 2010 and 2012 are non-conforming when returning movable-only values. I'm sure this first version will have several bugs, but let me know if this is a good starting point. Best, Ion
Le 11/02/14 14:11, Ion Gaztañaga a écrit :
El 11/02/2014 8:55, Adam Romanek escribió:
Hi!
Some time ago I encountered a problem with assigning the return value of boost::move() to a non-const reference in C++11 mode, but not in C++03 mode. See [1] for a StackOverflow question that I created for this issue. It contains all the details so for brevity I won't repeat them here. Could anyone explain this issue? Is this a limitation of C++03 emulation or a defect in the implementation?
Hi,
if I understand your function definition is not correct in C++11
|template
Yes, it's a limitation of boost move. When called with the emulation code boost::move() returns a type rv<T> & that is convertible to T (and that is the key point to implement emulated move semantics). However in C++11 you return a T&& (unnamed rvalue reference) which is not assignable to T &.
In your case, as R is std::ostream &, the emulation return rvstd::ostrean (convertible to std::ostream &) and the C++11 version returns std::ostream &&, which is not convertible to std::ostream &.
I guess we could add a new macro to boost move for return types. In emulated mode, it moves the return value, In C++11 mode it only return the value (If RVO can't be applied the compiler will do an implicit move). Something like:
//return boost::move(r) in emulation //return r in C++11 return BOOST_MOVE_RET(r);
What am I missing? Why you don't need to call std::move in the C++11 case? I don't think this works as the PO wants a move if the return type is not a non const reference. Best, Vicente
participants (5)
-
Adam Romanek
-
Ion Gaztañaga
-
Krzysztof Czainski
-
Lee Clagett
-
Vicente J. Botet Escriba