Search code examples
c++c++17memberstd-functionstdasync

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


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?


Solution

  • 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.