On Mon, Apr 9, 2012 at 3:14 PM, Vicente J. Botet Escriba
<vicente.botet@wanadoo.fr> wrote:
Le 09/04/12 20:06, Jeffrey Lee Hellrung, Jr. a écrit :
On Mon, Apr 9, 2012 at 10:41 AM, Vicente
J. Botet Escriba
<vicente.botet@wanadoo.fr>
wrote:
Le 08/04/12 17:18,
Jeffrey Lee Hellrung, Jr. a écrit :
After the commit some error have appeared on the regression
test (see below). It seems that the rvalue reference
semantic has changed a lot for gcc. I will try to use the
last design for this compiler version. Then I'll see what
needs to be done for other compilers as soon as results
appear on the regression tests page.
TBH, I wasn't really sure exactly what problem you were trying
to address with that patch, and how it addressed that :/ Care
to recap?
Note that I think we have 2 threads here on Boost.Thread, one
regarding VS 2010 and one regarding Sun. I might be getting
them confused.
Hi,
Sorry for all this noise.
No problem! I just want to be sure we're on the same page. I'm not very familiar with the thread library but I thought I could contribute to this problem in some way :/
I'm replaying to the error signaled on this thread and it concerns
VS 2010 (not Sun) and concerns also other compilers (in particular I
tested the example below with clang 3.0, gcc-4.6.2,4.7.0)
The signaled error was
E:\boost_1_49\boost/thread/future.hpp(1251): error C2535:
'boost::detail::task_object<R,F>::task_object(F)' : member
function already defined or declared
with
[
R=size_t,
F=std::tr1::_Bind<size_t,size_t,std::tr1::_Bind1<std::tr1::_Callable_fun<size_t
(__cdecl *const )(std::string &),false>,const char *>>
&
]
E:\boost_1_49\boost/thread/future.hpp(1247) : see
declaration of 'boost::detail::task_object<R,F>::task_object'
with
[
R=size_t,
F=std::tr1::_Bind<size_t,size_t,std::tr1::_Bind1<std::tr1::_Callable_fun<size_t
(__cdecl *const )(std::string &),false>,const char *>>
&
]
The concerned code is
template<typename R,typename F>
struct task_object:
task_base<R>
{
F f;
task_object(F const& f_):
f(f_)
{}
task_object(F&& f_):
f(f_)
{}
template<typename R>
class packaged_task
{
template <class F>
explicit packaged_task(F const& f):
task(new
detail::task_object<R,F>(f)),future_obtained(false)
{}
explicit packaged_task(R(*f)()):
task(new
detail::task_object<R,R(*)()>(f)),future_obtained(false)
{}
template <class F>
explicit packaged_task(F&& f):
task(new
detail::task_object<R,F>(f)),future_obtained(false) // *** 1
{}
I think the error comes from the following line in the example (see
***2 below)
async_func_pt<RetType>* p= new async_func_pt<RetType>
(boost::packaged_task<RetType>(f));
that should forward the reference while passing f.
async_func_pt<RetType>* p= new async_func_pt<RetType>
(boost::packaged_task<RetType>(std::forward<F>(f)));
because otherwise I believe the deduced template type is F&. Am
I right?
I think you're (partially) right.
When F& was given to the constructor of packaged_task it
instantiated task_object<R,F&>
As the same error were in the the Boost.Thread code in (1) above.
The use of forward solves the issue
task(new
detail::task_object<R,F>(boost::forward<F>(f))),future_obtained(false)
// *** 1
So the instantiated constructors were
task_object( const F& & f_):
f(f_)
{}
task_object(F& && f_):
f(f_)
{}
which produced the ambiguity.
Agreed.
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.
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!
Best,
Vicente
P.S. I have committed the example as test_ml.cpp with some
modifications.
I have rolled back the code adding the forward calls and I'll commit
it in trunk as sonn as the whole regression works on all the
compiler I can test.
======================================================
#include "boost/test/unit_test.hpp"
#include "boost/thread/future.hpp"
#include "boost/utility/result_of.hpp"
#include <functional>
struct async_func {
virtual ~async_func() { }
virtual void run() =0;
};
template <typename Ret>
class async_func_pt : public async_func {
boost::packaged_task<Ret> f;
public:
void run() override { f(); }
async_func_pt (boost::packaged_task<Ret>&& f) :
f(std::move(f)) {}
~async_func_pt() { }
boost::unique_future<Ret> get_future() { return
f.get_future(); }
};
void async_core (async_func* p);
template <typename F>
boost::unique_future<typename boost::result_of< F()
>::type>
async (F&& f)
{
typedef typename boost::result_of< F() >::type RetType;
async_func_pt<RetType>* p= new async_func_pt<RetType>
(boost::packaged_task<RetType>(f));
// ***2
boost::unique_future<RetType> future_result=
p->get_future();
async_core (p);
return std::move(future_result);
}
template <typename F, typename A1>
boost::unique_future<typename boost::result_of< F(A1)
>::type>
async (F&& f, A1&& a1)
{
// This should be all it needs. But get a funny error deep inside
Boost.
// problem overloading with && ?
return async (std::tr1::bind(f,a1));
}
BOOST_AUTO_TEST_SUITE(thread_pool_tests)
int calculate_the_answer_to_life_the_universe_and_everything()
{
return 42;
}
size_t foo (const std::string& s)
{
return s.size();
}
BOOST_AUTO_TEST_CASE( async_test )
{
// this one works
// most fundimental form:
boost::unique_future<int> fi= async
(&calculate_the_answer_to_life_the_universe_and_everything);
int i= fi.get();
BOOST_CHECK_EQUAL (i, 42);
// This one chokes at compile time
boost::unique_future<size_t> fut_1= async (&foo,
"Life");
BOOST_CHECK_EQUAL (fut_1.get(), 4);
}
BOOST_AUTO_TEST_SUITE_END()
_______________________________________________
Boost-users mailing list
Boost-users@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/boost-users