0

I'm trying to implement js style async/await. the function below returns a function that returns std::future object.

template <typename TResult, typename... TArgs>
std::function<std::future<TResult>(TArgs...)> async(std::function<TResult(TArgs...)> callback) {
    return [=]() {
        return std::async(std::launch::async, callback);
    };
}

and I execute the function like below:

auto test = asyncTest([=](const std::string &text) mutable {
    static int i = 0;
    await(1000);
    titleText.set(std::to_string(i) + text);
    i++;
});

test("asdf");

I got a compile error with this thing:

error: no matching function for call to 'async'

and

note: candidate template ignored: could not match 'function<type-parameter-0-0 (type-parameter-0-1...)>' against '(lambda)'

How can I make the template infers the type of the return value and the arguments?

ChrisMM
  • 8,448
  • 13
  • 29
  • 48
Tempus
  • 97
  • 1
  • 1
  • 8
  • 3
    do you actually need to know the signature of the `std::function` ? Why not `template auto async(F f) { ... }` ? (this wont return a `std::function` though) – 463035818_is_not_an_ai May 30 '22 at 17:41
  • 3
    Your problem is that a lambda is not a std::function. template deduction doesn't do any conversions. looking for a dupe – NathanOliver May 30 '22 at 17:49
  • 1
    You cannot infer the argument in the general case since it may not be unique. E.g. what happens, if you pass a `struct Foo{ void operator()(int){} void operator()(double){}};` ? – fabian May 30 '22 at 17:49
  • 1
    Note that something that can be done is returning a object providing a templated call operator that forwards the arguments to `std::async`: `template struct FunctionCaller { template auto operator()(Args&&...args) { return std::async(std::launch::async, m_f, std::forward(args)...); } F m_f; }; template auto asyncTest(F&& f) { return FunctionCaller{ std::forward(f) }; }` – fabian May 30 '22 at 18:03

0 Answers0