On Jun 17, 2013, at 1:28 PM, Klaim - Joël Lamotte
On Tue, Apr 2, 2013 at 7:16 PM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
I've started to use C++11 lambda functions with Boost.Thread.
The following works with clang-3.2
boost::future<int> f1 = boost::async( []() -> int {return 123;} );
But it fails with gcc-4.6.2, 4.7.2 and 4.8.0
../example/lambda_future.cpp:**25:91: erreur: conversion from ‘boost::future<void>’ to non-scalar type ‘boost::future<int>’ requested boost::future<int> f1 = boost::async( []() -> int {return 123;} );
The current implementation of boost::async uses boost::result_of to get the result type of the callable parameter.
Is this a know bug on boost::result_of or gcc compiler?
I'm seeing exactly the same behaviour in *VS2012 Update 2*. I'm using Boost 1.54.0 beta *r84748*
To be more precise:
1) I first was just using boost::future and tried to use the new .then(), here is a full repro:
#include
auto ft = boost::async( []{ return 42; } ).then( []( boost::future<int> r ){ return 666; } );
This fails because boost::async() returned a future<void> instead of a future<int>. I suspect the then() call to have the same problem. I can provide the full error log but I think it's not that useful.
2) Just to be sure I tried this full test:
#include
int main() { auto ft = boost::async( []{ return 42; } ); // SUCCEED: static_assert( std::is_same< decltype(ft), boost::future<void> >::value, "WTF???" ); // FAILS: static_assert( std::is_same< decltype(ft), boost::future<int> >::value, "Not the expected type!" ); }
Both asserts confirm that I don't get what I want.
3) I remembered that there were some issues from usage of boost::result_of in Boost.Log, so to clarify the situation I setup the following full test:
#include
#include int top() { return 42; } struct K { int operator()(){ return 42; }
typedef int value_type; };
auto F = []{ return 42; };
int main() { // A: ALL SUCCEED static_assert( std::is_same< decltype(K()()), int >::value, "Not the expected type!" ); static_assert( std::is_same< decltype(top()), int >::value, "Not the expected type!" ); static_assert( std::is_same< decltype(F()), int >::value, "Not the expected type!" );
// B: ALL SUCCEED static_assert( std::is_same< std::result_of
::type, int >::value, "Not the expected type!" ); static_assert( std::is_same< std::result_of ::type, int ::value, "Not the expected type!" ); static_assert( std::is_same< std::result_of
::type, int ::value, "Not the expected type!" ); // C: ALL SUCCEED std::result_of
::type a = K()(); std::result_of ::type b = top(); std::result_of ::type c = F(); // D: ALL FAILS static_assert( std::is_same< boost::result_of
::type, int >::value, "Not the expected type!" ); static_assert( std::is_same< boost::result_of ::type, int ::value, "Not the expected type!" ); static_assert( std::is_same< boost::result_of
::type, int ::value, "Not the expected type!" ); // E: ALL FAILS boost::result_of ::type d = K()(); // error C2182: 'd' : illegal use of type 'void' boost::result_of ::type e = top(); // error C2182: 'e' : illegal use of type 'void' boost::result_of ::type f = F(); // error C2182: 'f' : illegal use of type 'void' }
This shows clearly that:
1. boost::result_of don't behave like std::result_of on this platform (and from previous discussions, on other platforms too). 2. both std::result_of and decltype() provide the result I expect from reading documentations about these.
So far I'm assuming that the problem really is from boost::result_of, but I might be wrong because the differences with std::result_of are not clear to me.
----
Unfortunately this makes future.then() unusable if we expect return types. I don't know if it impacts other libraries (I suspect Boost.Log).
Should I report a bug or is it known, already fixed or a misuse?
If I'm not mistaken, it looks like you are using the TR1 protocol with nullary functions. See the bullet point on nullary functions in the documentation. http://www.boost.org/doc/libs/1_53_0/libs/utility/utility.htm#result_of_tr1_... TR1 cannot deduce the return type of nullary function objects. You probably either want to use std::result_of or boost::result_of with BOOST_RESULT_OF_USE_DECLTYPE defined. If you really must use TR1 there are workarounds for the nullary function issue discussed at the same bullet point at the link above, but these workarounds may not be applicable in your situation. In C++11, I would not recommend using TR1 unless you need it for backwards compatibility/portability to C++03, in which case you can't deduce return types for nullary function objects. - Daniel