Le 10/04/12 01:24, Jeffrey Lee Hellrung, Jr. a écrit :
On Mon, Apr 9, 2012 at 3:14 PM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:

There are yet some problems on the Boost.Thread implementation or with the compilers implementation.

When I want to pass functor, as in

A a(5);
boost::packaged_task<int> pt(a);

the constructor used is packaged_task(F&& f) and I will expect packaged_task(F const& f) to be use for.
Are my expectations correct?

Well...no, apparently your expectations are not correct. But that's slightly beside the point. I think the correct fix here is to remove the packaged_task(F const &) overload entirely, since the packaged_task(F&&) overload already covers it (that's part of the entire design of "templated rvalue references", to capture both rvalues *and* lvalues). Then instantiate task_object with something like remove_cv< remove_reference<F>::type >::type, and use boost::forward<F>(f) to pass the function object down to the task_object constructor.
Yeah, this is the point. packaged_task(F const &) overload was not used never, and task_object  was instantiated as task_object<R,A&>. I have a patch that seems to work (see below I have not used remove_cv yet, but I agree it should be needed to take care of const functors).

The overload

        explicit packaged_task(R(*f)()):
            task(new detail::task_object<R,R(*)()>(f)),future_obtained(false)
        {}

seems necessary because otherwise the task_object is instantiated with <R,R()> which is not what we want.
Do you have an hint on how simplify this?

The test futures/packaged_task/alloc_ctor_pass.cpp gives this context.

Thanks for your patience and perseverance.

And thank you for clarifying the issue for me!


Please, could you check the patch and see if there is something that can be improved.

Thanks for all,
Vicente

iMac-de-Vicente-Botet-Escriba:trunk viboes$ svn diff boost/thread libs/thread
Index: boost/thread/future.hpp
===================================================================
--- boost/thread/future.hpp    (revision 77870)
+++ boost/thread/future.hpp    (working copy)
@@ -19,6 +19,7 @@
 #include <boost/scoped_ptr.hpp>
 #include <boost/type_traits/is_fundamental.hpp>
 #include <boost/type_traits/is_convertible.hpp>
+#include <boost/type_traits/remove_reference.hpp>
 #include <boost/mpl/if.hpp>
 #include <boost/config.hpp>
 #include <boost/throw_exception.hpp>
@@ -1807,16 +1808,16 @@
         explicit packaged_task(R(*f)()):
             task(new detail::task_object<R,R(*)()>(f)),future_obtained(false)
         {}
-        template <class F>
-        explicit packaged_task(F const& f):
-            task(new detail::task_object<R,F>(f)),future_obtained(false)
-        {}
 #ifndef BOOST_NO_RVALUE_REFERENCES
         template <class F>
         explicit packaged_task(F&& f):
-            task(new detail::task_object<R,F>(boost::forward<F>(f))),future_obtained(false)
+            task(new detail::task_object<R,typename remove_reference<F>::type>(boost::forward<F>(f))),future_obtained(false)
         {}
 #else
+        template <class F>
+        explicit packaged_task(F const& f):
+            task(new detail::task_object<R,F>(f)),future_obtained(false)
+        {}
 #if defined BOOST_THREAD_USES_MOVE
         template <class F>
         explicit packaged_task(boost::rv<F>& f):
@@ -1831,29 +1832,30 @@
 #endif
 
 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
+#ifndef BOOST_NO_RVALUE_REFERENCES
         template <class F, class Allocator>
-        packaged_task(boost::allocator_arg_t, Allocator a, const F& f)
+        packaged_task(boost::allocator_arg_t, Allocator a, F&& f)
         {
-          typedef typename Allocator::template rebind<detail::task_object<R,F> >::other A2;
+          typedef typename remove_reference<F>::type FR;
+          typedef typename Allocator::template rebind<detail::task_object<R,FR> >::other A2;
           A2 a2(a);
           typedef thread_detail::allocator_destructor<A2> D;
 
-          task = task_ptr(::new(a2.allocate(1)) detail::task_object<R,F>(f), D(a2, 1) );
-          std::cout << __FILE__ ":"<<__LINE__<<std::endl;
+          task = task_ptr(::new(a2.allocate(1)) detail::task_object<R,FR>(boost::forward<F>(f)), D(a2, 1) );
           future_obtained = false;
         }
-#ifndef BOOST_NO_RVALUE_REFERENCES
+#else
         template <class F, class Allocator>
-        packaged_task(boost::allocator_arg_t, Allocator a, F&& f)
+        packaged_task(boost::allocator_arg_t, Allocator a, const F& f)
         {
           typedef typename Allocator::template rebind<detail::task_object<R,F> >::other A2;
           A2 a2(a);
           typedef thread_detail::allocator_destructor<A2> D;
 
-          task = task_ptr(::new(a2.allocate(1)) detail::task_object<R,F>(boost::forward<F>(f)), D(a2, 1) );
+          task = task_ptr(::new(a2.allocate(1)) detail::task_object<R,F>(f), D(a2, 1) );
+          std::cout << __FILE__ ":"<<__LINE__<<std::endl;
           future_obtained = false;
         }
-#else
 #if defined BOOST_THREAD_USES_MOVE
         template <class F, class Allocator>
         packaged_task(boost::allocator_arg_t, Allocator a, boost::rv<F>& f)