[Boost.Thread] unique_future without && ?
My code needs to be compatible with a platform that doesn't have rvalue references available, for the time being. I've avoided explicit uses of move and made my && arguments fall back to const&. But I'm not sure about returning a unique_future. I see that unique_future<T> has a special move-the-guts type, with an implicit conversion operator and a constructor. But do I need to do anything special to declare a function returning one, and likewise the return statement itself? The code in packaged_task ( unique_future<R> packaged_task<R>::get_future() ) is not conditionally compiled based on BOOST_NO_RVALUE_REFERENCES, so I'm supposing that it just works by itself. Is that correct? But maybe it only works by itself in some cases? In that code, the return statement names a constructor directly. return unique_future<R>(task); In my code, I'm returning a unique_future that I already made somewhere else (actually, the result of another function call) so it would be wanting to call the copy constructor, I would think. So if I write unique_future<int> foo(); unique_future<int> bar() { return foo(); } what _should_ happen is that the existing value uses a user-defined conversion to construct the "copy", right? So I should expect this to work correctly if the thing I'm returning is already exactly the right type, as well as when naming the constructor directly. —John
Le 06/04/12 09:20, John M. Dlugosz a écrit :
My code needs to be compatible with a platform that doesn't have rvalue references available, for the time being. Which platform and compiler?
I've avoided explicit uses of move and made my && arguments fall back to const&. But I'm not sure about returning a unique_future. I see that unique_future<T> has a special move-the-guts type, with an implicit conversion operator and a constructor. But do I need to do anything special to declare a function returning one, and likewise the return statement itself? The code in packaged_task ( unique_future<R> packaged_task<R>::get_future() ) is not conditionally compiled based on BOOST_NO_RVALUE_REFERENCES, so I'm supposing that it just works by itself. Is that correct?
But maybe it only works by itself in some cases? In that code, the return statement names a constructor directly. return unique_future<R>(task);
In my code, I'm returning a unique_future that I already made somewhere else (actually, the result of another function call) so it would be wanting to call the copy constructor, I would think.
So if I write unique_future<int> foo(); unique_future<int> bar() { return foo(); }
what _should_ happen is that the existing value uses a user-defined conversion to construct the "copy", right? So I should expect this to work correctly if the thing I'm returning is already exactly the right type, as well as when naming the constructor directly.
The released implementation doesn't manage well returning rvalue. The trunk has been refactored a lot of code and it allows to manage with rvalue references. Could you tru with the trunk unique_future<int> foo(); unique_future<int> bar() { return BOOST_EXPLICT_MOVE(foo()); } HTH, Vicente
On Fri, Apr 6, 2012 at 9:25 AM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Le 06/04/12 09:20, John M. Dlugosz a écrit :
My code needs to be compatible with a platform that doesn't have rvalue references available, for the time being.
Which platform and compiler?
I've avoided explicit uses of move and made my && arguments fall back to
const&. But I'm not sure about returning a unique_future. I see that unique_future<T> has a special move-the-guts type, with an implicit conversion operator and a constructor. But do I need to do anything special to declare a function returning one, and likewise the return statement itself? The code in packaged_task ( unique_future<R> packaged_task<R>::get_future() ) is not conditionally compiled based on BOOST_NO_RVALUE_REFERENCES, so I'm supposing that it just works by itself. Is that correct?
But maybe it only works by itself in some cases? In that code, the return statement names a constructor directly. return unique_future<R>(task);
In my code, I'm returning a unique_future that I already made somewhere else (actually, the result of another function call) so it would be wanting to call the copy constructor, I would think.
So if I write unique_future<int> foo(); unique_future<int> bar() { return foo(); }
what _should_ happen is that the existing value uses a user-defined conversion to construct the "copy", right? So I should expect this to work correctly if the thing I'm returning is already exactly the right type, as well as when naming the constructor directly.
The released implementation doesn't manage well returning rvalue.
Eh? Why not? Correct me if I'm wrong, but I don't think you have to do anything special to return values of move-emulation-enabled types (whether only movable or movable+copyable) and ensure the move constructor kicks in. E.g., X foo() { return X(/*...*/); } X bar() { X result(/*...*/); return boost::move(result); } should not create spurious copies (or compiler errors) whether in C++03 or C++11. The trunk has been refactored a lot of code and it allows to manage with
rvalue references. Could you tru with the trunk
unique_future<int> foo(); unique_future<int> bar() { return BOOST_EXPLICT_MOVE(foo()); }
Again, I don't think the use of the BOOST_EXPLICIT_MOVE macro is necessary in this case. We aren't assigning the result of foo() to an existing unique_future<int> object, we're (logically) constructing a new unique_future<int> object, and that, AFAIK, has never been a problem with the move emulation provided by Boost.Move. - Jeff
Le 06/04/12 18:47, Jeffrey Lee Hellrung, Jr. a écrit :
On Fri, Apr 6, 2012 at 9:25 AM, Vicente J. Botet Escriba
mailto:vicente.botet@wanadoo.fr> wrote: Le 06/04/12 09:20, John M. Dlugosz a écrit :
My code needs to be compatible with a platform that doesn't have rvalue references available, for the time being.
Which platform and compiler?
I've avoided explicit uses of move and made my && arguments fall back to const&. But I'm not sure about returning a unique_future. I see that unique_future<T> has a special move-the-guts type, with an implicit conversion operator and a constructor. But do I need to do anything special to declare a function returning one, and likewise the return statement itself? The code in packaged_task ( unique_future<R> packaged_task<R>::get_future() ) is not conditionally compiled based on BOOST_NO_RVALUE_REFERENCES, so I'm supposing that it just works by itself. Is that correct?
But maybe it only works by itself in some cases? In that code, the return statement names a constructor directly. return unique_future<R>(task);
In my code, I'm returning a unique_future that I already made somewhere else (actually, the result of another function call) so it would be wanting to call the copy constructor, I would think.
So if I write unique_future<int> foo(); unique_future<int> bar() { return foo(); }
what _should_ happen is that the existing value uses a user-defined conversion to construct the "copy", right? So I should expect this to work correctly if the thing I'm returning is already exactly the right type, as well as when naming the constructor directly.
The released implementation doesn't manage well returning rvalue.
Eh? Why not? Correct me if I'm wrong, but I don't think you have to do anything special to return values of move-emulation-enabled types (whether only movable or movable+copyable) and ensure the move constructor kicks in. E.g.,
X foo() { return X(/*...*/); } X bar() { X result(/*...*/); return boost::move(result); }
Yes, this works well. But here we don't return a rvalue, isn't it?
should not create spurious copies (or compiler errors) whether in C++03 or C++11.
The trunk has been refactored a lot of code and it allows to manage with rvalue references. Could you tru with the trunk
unique_future<int> foo(); unique_future<int> bar() { return BOOST_EXPLICIT_MOVE(foo()); }
Again, I don't think the use of the BOOST_EXPLICIT_MOVE macro is necessary in this case. We aren't assigning the result of foo() to an existing unique_future<int> object, we're (logically) constructing a new unique_future<int> object, and that, AFAIK, has never been a problem with the move emulation provided by Boost.Move. Hi Jeff,
you are right on most of the points with most of the compilers. But see the results of Boost.Move with Sun. Here the use of BOOST_EXPLICIT_MOVE helps a lot without the need of declaring a local variable. Best, Vicente
On Fri, Apr 6, 2012 at 10:05 AM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Le 06/04/12 18:47, Jeffrey Lee Hellrung, Jr. a écrit :
On Fri, Apr 6, 2012 at 9:25 AM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Le 06/04/12 09:20, John M. Dlugosz a écrit :
My code needs to be compatible with a platform that doesn't have rvalue references available, for the time being.
Which platform and compiler?
I've avoided explicit uses of move and made my && arguments fall back to
const&. But I'm not sure about returning a unique_future. I see that unique_future<T> has a special move-the-guts type, with an implicit conversion operator and a constructor. But do I need to do anything special to declare a function returning one, and likewise the return statement itself? The code in packaged_task ( unique_future<R> packaged_task<R>::get_future() ) is not conditionally compiled based on BOOST_NO_RVALUE_REFERENCES, so I'm supposing that it just works by itself. Is that correct?
But maybe it only works by itself in some cases? In that code, the return statement names a constructor directly. return unique_future<R>(task);
In my code, I'm returning a unique_future that I already made somewhere else (actually, the result of another function call) so it would be wanting to call the copy constructor, I would think.
So if I write unique_future<int> foo(); unique_future<int> bar() { return foo(); }
what _should_ happen is that the existing value uses a user-defined conversion to construct the "copy", right? So I should expect this to work correctly if the thing I'm returning is already exactly the right type, as well as when naming the constructor directly.
The released implementation doesn't manage well returning rvalue.
Eh? Why not? Correct me if I'm wrong, but I don't think you have to do anything special to return values of move-emulation-enabled types (whether only movable or movable+copyable) and ensure the move constructor kicks in. E.g.,
X foo() { return X(/*...*/); } X bar() { X result(/*...*/); return boost::move(result); }
Yes, this works well. But here we don't return a rvalue, isn't it?
It shouldn't make a difference. The original foo bar example should work as well. should not create spurious copies (or compiler errors) whether in C++03 or
C++11.
The trunk has been refactored a lot of code and it allows to manage with
rvalue references. Could you tru with the trunk
unique_future<int> foo(); unique_future<int> bar() { return BOOST_EXPLICIT_MOVE(foo()); }
Again, I don't think the use of the BOOST_EXPLICIT_MOVE macro is necessary in this case. We aren't assigning the result of foo() to an existing unique_future<int> object, we're (logically) constructing a new unique_future<int> object, and that, AFAIK, has never been a problem with the move emulation provided by Boost.Move.
Hi Jeff,
you are right on most of the points with most of the compilers. But see the results of Boost.Move with Sun. Here the use of BOOST_EXPLICIT_MOVE helps a lot without the need of declaring a local variable.
Which results are you referring to? What do you mean by "helps a lot"? I wasn't aware that Sun had issues with C++03 move emulation. What specific C++03 feature is Sun failing to implement? - Jeff
Le 07/04/12 20:27, Jeffrey Lee Hellrung, Jr. a écrit :
On Fri, Apr 6, 2012 at 10:05 AM, Vicente J. Botet Escriba
mailto:vicente.botet@wanadoo.fr> wrote: Le 06/04/12 18:47, Jeffrey Lee Hellrung, Jr. a écrit :
On Fri, Apr 6, 2012 at 9:25 AM, Vicente J. Botet Escriba
mailto:vicente.botet@wanadoo.fr> wrote: Le 06/04/12 09:20, John M. Dlugosz a écrit :
My code needs to be compatible with a platform that doesn't have rvalue references available, for the time being.
Which platform and compiler?
The released implementation doesn't manage well returning rvalue.
Eh? Why not? Correct me if I'm wrong, but I don't think you have to do anything special to return values of move-emulation-enabled types (whether only movable or movable+copyable) and ensure the move constructor kicks in. E.g.,
X foo() { return X(/*...*/); } X bar() { X result(/*...*/); return boost::move(result); }
Yes, this works well. But here we don't return a rvalue, isn't it?
It shouldn't make a difference. The original foo bar example should work as well.
should not create spurious copies (or compiler errors) whether in C++03 or C++11.
The trunk has been refactored a lot of code and it allows to manage with rvalue references. Could you tru with the trunk
unique_future<int> foo(); unique_future<int> bar() { return BOOST_EXPLICIT_MOVE(foo()); }
Again, I don't think the use of the BOOST_EXPLICIT_MOVE macro is necessary in this case. We aren't assigning the result of foo() to an existing unique_future<int> object, we're (logically) constructing a new unique_future<int> object, and that, AFAIK, has never been a problem with the move emulation provided by Boost.Move.
Hi Jeff,
you are right on most of the points with most of the compilers. But see the results of Boost.Move with Sun. Here the use of BOOST_EXPLICIT_MOVE helps a lot without the need of declaring a local variable.
Which results are you referring to? What do you mean by "helps a lot"? I wasn't aware that Sun had issues with C++03 move emulation. What specific C++03 feature is Sun failing to implement?
The following doesn't compiles with Sun compiler boost::future<int> f = p.get_future(); "../libs/thread/test/sync/futures/promise/alloc_ctor_pass.cpp", line 34: Error: boost::future<int>::future(boost::future<int>&) is not accessible from main(). When I force the explicit conversion it works. boost::future<int> f = BOOST_EXPLICIT_MOVE(p.get_future()); I guess this is because even if the copy constructor is private Sun Compiler prefers the private overload to the move constructor that needs an implicit conversion. Best, Vicente
On Sun, Apr 8, 2012 at 3:01 AM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Le 07/04/12 20:27, Jeffrey Lee Hellrung, Jr. a écrit :
On Fri, Apr 6, 2012 at 10:05 AM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Le 06/04/12 18:47, Jeffrey Lee Hellrung, Jr. a écrit :
On Fri, Apr 6, 2012 at 9:25 AM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Le 06/04/12 09:20, John M. Dlugosz a écrit :
My code needs to be compatible with a platform that doesn't have rvalue references available, for the time being.
Which platform and compiler?
The released implementation doesn't manage well returning rvalue.
Eh? Why not? Correct me if I'm wrong, but I don't think you have to do anything special to return values of move-emulation-enabled types (whether only movable or movable+copyable) and ensure the move constructor kicks in. E.g.,
X foo() { return X(/*...*/); } X bar() { X result(/*...*/); return boost::move(result); }
Yes, this works well. But here we don't return a rvalue, isn't it?
It shouldn't make a difference. The original foo bar example should work as well.
should not create spurious copies (or compiler errors) whether in
C++03 or C++11.
The trunk has been refactored a lot of code and it allows to manage
with rvalue references. Could you tru with the trunk
unique_future<int> foo(); unique_future<int> bar() { return BOOST_EXPLICIT_MOVE(foo()); }
Again, I don't think the use of the BOOST_EXPLICIT_MOVE macro is necessary in this case. We aren't assigning the result of foo() to an existing unique_future<int> object, we're (logically) constructing a new unique_future<int> object, and that, AFAIK, has never been a problem with the move emulation provided by Boost.Move.
Hi Jeff,
you are right on most of the points with most of the compilers. But see the results of Boost.Move with Sun. Here the use of BOOST_EXPLICIT_MOVE helps a lot without the need of declaring a local variable.
Which results are you referring to? What do you mean by "helps a lot"? I wasn't aware that Sun had issues with C++03 move emulation. What specific C++03 feature is Sun failing to implement?
The following doesn't compiles with Sun compiler
boost::future<int> f = p.get_future();
"../libs/thread/test/sync/futures/promise/alloc_ctor_pass.cpp", line 34: Error: boost::future<int>::future(boost::future<int>&) is not accessible from main().
When I force the explicit conversion it works.
boost::future<int> f = BOOST_EXPLICIT_MOVE(p.get_future());
I guess this is because even if the copy constructor is private Sun Compiler prefers the private overload to the move constructor that needs an implicit conversion.
Well the accessibility of a member function never influences its position in an overload set (AFAIK). What is *suppose* to happen in C++03 for the above example is that the future::future(rv< future >&) overload gets called, since a future rvalue isn't suppose to be bindable to the argument of the (private and undefined) future::future(future&) overload. That's clearly not happening :( I can't think of a fix other than making your intentions very explicit as you've done above :/ Thanks for the explanation, - Jeff
On 4/8/2012 10:25 AM, Jeffrey Lee Hellrung, Jr. wrote:
Well the accessibility of a member function never influences its position in an overload set (AFAIK). What is *suppose* to happen in C++03 for the above example is that the future::future(rv< future >&) overload gets called, since a future rvalue isn't suppose to be bindable to the argument of the (private and undefined) future::future(future&) overload. That's clearly not happening :( I can't think of a fix other than making your intentions very explicit as you've done above :/
So, does anyone have any insight on the VS10 error? If it's a straightforward compiler bug (not allowing T&& and const T& to be overloaded sets) I think that would have been discovered and get in the way _everywhere_. —John
On Mon, Apr 9, 2012 at 9:04 AM, John M. Dlugosz
On 4/8/2012 10:25 AM, Jeffrey Lee Hellrung, Jr. wrote:
Well the accessibility of a member function never influences its position
in an overload set (AFAIK). What is *suppose* to happen in C++03 for the above example is that the future::future(rv< future >&) overload gets called, since a future rvalue isn't suppose to be bindable to the argument of the (private and undefined) future::future(future&) overload. That's clearly not happening :( I can't think of a fix other than making your intentions very explicit as you've done above :/
So, does anyone have any insight on the VS10 error? If it's a straightforward compiler bug (not allowing T&& and const T& to be overloaded sets) I think that would have been discovered and get in the way _everywhere_.
AFAIK the problem was that T is bound to a (lvalue) reference, causing T&& == T const &. I'm confused, though, as the quoted comment above referred to a problem with the Sun compiler, not the Visual Studio compiler... - Jeff
participants (3)
-
Jeffrey Lee Hellrung, Jr.
-
John M. Dlugosz
-
Vicente J. Botet Escriba