std::async with non static member functions

Viewed 1332

I am trying to evaluate a part of my code asynchronously

#include <stdio.h>
#include <string>
#include <memory>
#include <future>
#include <map>

namespace IG
{
    typedef std::map<uint, std::string> CadDef;

    class FooFoo
    {
        CadDef foo()
        {
            CadDef cdef{};
            cdef[1] = "aa";
            return cdef;
        }
    };
}

int main()
{
    auto ptr = std::make_unique<IG::FooFoo>();
    std::future<IG::CadDef> resFut = std::async(ptr->foo);
    auto res = resFut.get();
    return 0;
}

But the code doesn't compile - (On gcc)

error: invalid use of non-static member function ‘IG::CadDef IG::FooFoo::foo()’

(on msvc -- my main program, from where I abstracted the minimal example)

error C3867: 'IG::FooFoo::foo': non-standard syntax; use '&' to create a pointer to member
error C2672: 'std::async': no matching overloaded function found
error C2780: 'std::future<_Invoke_traits<void,decay<_Ty>::type,decay<_ArgTypes>::type...>::type> std::async(std::launch,_Fty &&,_ArgTypes &&...)': expects 3 arguments - 1 provided

Seems like MSVC is complaining that I have not used ptr->foo() but I am not sure.

What am I doing wrong?

2 Answers

You can use a lambda like following, using a policy*

auto handle = std::async(std::launch::async, [&ptr](){
        return ptr->foo(); // Ofcourse make foo public in your snippet
});


auto res = handle.get();

*Not necessarily required

Async takes a function address as an argument, but it the function is a class-member function you have to bind it to the object which can invoke this function.

All functions (including methods) are moved to the code segment of the binary file. That's why the sizeof(T) equals to sum of sizeof of all class data-members (including a virtual table pointer (vptr) if exists).

class A {void method() }; can be represented as void method(A* a) {}

Knowing all this information you should bind the method with the object

int main()
{
    auto ptr = std::make_unique<IG::FooFoo>();
    std::future<IG::CadDef> resFut = std::async(&IG::FooFoo::foo, ptr.get());
    auto res = resFut.get();
    return 0;
}
Related