std::async with a member function, holding another meber fucntion as an argument

45 views Asked by At

I have the following class:

class Test
{
public:   
   void Func1(std::string const& a, std::string const& b, std::function<void(std::vector<double> const&, int)> func);   
   std::vector<double> Func2(std::vector<double> const& v, size_t const i);
};

To asynchronously call the function Func1 I did:

Test te;
auto fa = std::bind(&Test::Func2, &te, _1, _2);
auto fb = std::bind(&Test::Func1, &te, a, b, fa);
    
auto fab = std::async(std::launch::async, fb);

The 'fa' and 'fb' compiles but the async call 'fab' doesn't. How should I call the std::async for Func1?

1

There are 1 answers

2
Kuba hasn't forgotten Monica On BEST ANSWER

fa and fb don't fully "compile" until you actually call them - the function call operators aren't instantiated till then, it seems. Once you call, you'll realize that fb is invalid, i.e. fb() won't compile. As soon as you fix that, the async call will work :)

As a further hint, observe that std::bind is subtly broken and not recommended for new code. You'd be better served with lambdas (they'd actually work here!).

How is bind broken? Like so:

std::bind(&Test::Func1, &te, a, b, fa)(); // won't compile

But:

using FnArg = std::function<void(std::vector<double> const&, int)>;
fb = std::bind(&Test::Func1, &te, a, b, FnArg(fa));
fb(); // compiles OK

So, you'd be best served by forgetting about std::bind's existence, and use lambdas:

#include <functional>
#include <future>
#include <string>
#include <vector>

class Test
{
public:
    using FnArg = std::function<void(std::vector<double> const&, int)>;
    void Func1(std::string const&, std::string const&, FnArg) {}
    std::vector<double> Func2(std::vector<double> const&, size_t const) {}
};

int main()
{
    Test te;
    std::vector<double> vd;
    std::string a, b;
    auto fa = [&te](const auto &a, auto b){ return te.Func2(a, b); };
    auto fb = [=,&te](){ return te.Func1(a, b, fa); };
    fa(vd, 1);
    fb();
        
    auto fab = std::async(std::launch::async, fb);
    fab.wait();
}

Feel free to mess with it online.