Search code examples
c++boostfutureboost-thread

Type of boost::future<> from boost::async()


I am getting unexpected results from boost::async() (Boost 1.56, Windows: VS2010 and VS2012).

#include <boost/thread/future.hpp>
...
auto func = [](){ return 123; };
auto boostFut = boost::async(func);
// boostFut = 42; // intentional error to reveal deduced type in compilation error

For some reason boostFut is deduced as boost::unique_future<void> instead of boost::unique_future<int>.

What am I doing wrong?

Note: on VS2012, if I used std::async(func) instead of boost::async(func) it does work as expected and the future type is deduced as int.


Solution

  • boost::async needs to determine the resultant type of the argument functor's call. In order to do that, Boost uses its own boost::result_of<T> class template implementation. That is, async declaration looks as below:

    template <class F>
    boost::future<typename boost::result_of<typename boost::decay<F>::type()>::type>
    async(F f);
    

    Depending on the compiler's capabilities/boost's configuration, boost::result_of<T> trait may work in one of the two ways:

    1. Use decltype() from the call expression.
    2. Look for a nested result_type typedef within F or a nested result<T> class template within F (if a number of the functor's arguments is greater than zero, as overloads may exist).

    If the latter approach (2) is used, neither of the aforementioned alternatives are applicable for lambda's type, therefore Boost ends up with default assumption deducing void as a return type.

    To make sure your Boost implementation will use decltype() operator (that works for lambda's call expressions fine), you need to prepend a define prior to Boost headers inclusion:

    #define BOOST_RESULT_OF_USE_DECLTYPE
    

    or add this define to boost/config/user.hpp file.