Boost logo

Boost Users :

Subject: Re: [Boost-users] [move] differences between results in C++03 and C++11 modes
From: Vicente J. Botet Escriba (vicente.botet_at_[hidden])
Date: 2014-02-12 01:50:53


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 <class R, class F>
R call_under_lock(F f) {
   // lock();
   R r= f();
   // unlock();
   return boost::move(r);
}|

Would the following work for you in C++11?

|template <class R, class F>
R call_under_lock(F f) {
   locker lk(...);
   return f();
}|

If R is movable only, wouldn't the previous code work with the
Boost.Move emulation?

If you want to write your code using an intermediary variable shouldn't
you need an indirection, let me call it move_if_no_reference

|template <class R, class F>
R call_under_lock(F f) {
   // lock();
   R r= f();
   // unlock();
   return boost::move_if_no_reference<R>()(r);
}|

template <class T>
struct move_if_no_reference {
   T&& operator (T& v) noexcept { return std::move(v);}
};
template <class T>
struct move_if_no_reference<T&> {
   T& operator (T& v) noexcept {return v;};
};

||

> 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
> rv<std::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



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net