3

I am attempting to implement async with a packaged_task. I am attempting this via a templated function, bsync. bsync takes 2 arguments: a function,f, and a parameter-pack, args, and returns a future, fut. The future is of the type returned by f(args...). Ie - the return is future

I think I am almost there, but I am getting a type-conversion error. Any help would be appreciated:

#include "stdafx.h"
#include <iostream>
#include <future>
#include <thread>
#include <functional>
#include <type_traits>
using namespace std;


//Implement bsync as a templated function
//Template parameters are (i) Fn (the function to run), (ii) Args, a parameter pack of arguments to feed the function
//The function returns a future<Ret>, where Ret is the return-type of Fn(Args)
template<class Fn,class...Args>
auto bsync(Fn f, Args&&...args)->future<result_of<decltype(f)&(Args&&...)>>{

    //Determine return-type
    typedef result_of<decltype(f)&(Args&&...)>::type A;

    //Initialize a packaged_task
    packaged_task <A(Args&&...)>tsk(f);

    //Initialize a future
    future<A> fut = tsk.get_future();

    //Run the packaged task in a separate thread
    thread th(move(tsk),(args)...);

    //Join the thread
    th.join();

    return fut;
}

int plus_one(int x){
    cout << "Adding 1 to " << x << endl;
    return x++;
}

int main(){
    auto x = bsync(plus_one, 1);

    cout << "Press any key to continue:" << endl;
    cin.ignore();
    return 0;
}
Barry
  • 286,269
  • 29
  • 621
  • 977
  • First glaring problem: `future>`. You mean `future::type>`? (Also, since you have `Fn`, I'm not sure why you are using `decltype(f)` at all...) – T.C. May 04 '15 at 16:02

1 Answers1

3

Your trailing return type is incorrect. You have:

future<result_of<decltype(f)&(Args&&...)>>

That is a future with type result_of<...>. You need to actually evaluate the result_of metafunction to produce the actual result type. That is:

future<typename result_of<Fn(Args&&...)>::type>
       ^^^^^^^^^                        ^^^^^^

Once you fix that, you're missing a typename in your typedef for A.

Barry
  • 286,269
  • 29
  • 621
  • 977
  • Also, check if C++14 `result_of_t` is available from your compiler. – Yakk - Adam Nevraumont May 04 '15 at 16:19
  • Almost there - Taking a look at the main function. I can successfully pass bsync an arg&&, but not an arg. Eg: This works: int y=1; auto x = bsync(plus_one,y); This doesn't work: auto x = bsync(plus_one,1); I'm guessing my implementation is somewhere off in reference-hell - any ideas? – ice_planet_hoth_boss May 04 '15 at 18:14
  • @ice_planet_hoth_boss I assume you mean the opposite. That's because `thread` stores a copy of it's arguments, if you want to pass references you'll have to wrap them in `reference_wrapper`. See [Wakely's](http://stackoverflow.com/a/28975738/2069064) answer to a related question. – Barry May 04 '15 at 18:22