Boost logo

Boost :

Subject: Re: [boost] [utility][thread] result_of - erroneous result type from a C++11 lambda
From: Klaim - Joël Lamotte (mjklaim_at_[hidden])
Date: 2013-06-17 13:28:45


On Tue, Apr 2, 2013 at 7:16 PM, Vicente J. Botet Escriba <
vicente.botet_at_[hidden]> 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 <boost/thread/future.hpp>

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 <boost/thread/future.hpp>

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 <boost/utility/result_of.hpp>
#include <type_traits>

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<K()>::type, int >::value, "Not
the expected type!" );
static_assert( std::is_same< std::result_of<decltype(top)>::type, int
>::value, "Not the expected type!" );
static_assert( std::is_same< std::result_of<decltype(F)()>::type, int
>::value, "Not the expected type!" );

// C: ALL SUCCEED
std::result_of<K()>::type a = K()();
std::result_of<decltype(top)>::type b = top();
std::result_of<decltype(F)()>::type c = F();

// D: ALL FAILS
static_assert( std::is_same< boost::result_of<K()>::type, int >::value,
"Not the expected type!" );
static_assert( std::is_same< boost::result_of<decltype(top)>::type, int
>::value, "Not the expected type!" );
static_assert( std::is_same< boost::result_of<decltype(F)()>::type, int
>::value, "Not the expected type!" );
 // E: ALL FAILS
boost::result_of<K()>::type d = K()(); // error C2182: 'd' : illegal use of
type 'void'
boost::result_of<decltype(top)>::type e = top(); // error C2182: 'e' :
illegal use of type 'void'
boost::result_of<decltype(F)()>::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?
Joel Lamotte

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk