成员函数的std :: async调用

ste*_*fan 9 c++ asynchronous function-pointers class c++11

考虑以下课程:

class Foo
{
   private:
      void bar(const size_t);
   public:
      void foo();
};
Run Code Online (Sandbox Code Playgroud)

现在Foo::foo()应该启动线程执行bar,所以这是它的实现方式:

void Foo:foo()
{
    auto handle = std::async(std::launch::async, &Foo::bar, this, 0);
    handle.get();
}
Run Code Online (Sandbox Code Playgroud)

这与g ++ - 4.6.3完美配合,但与g ++ - 4.5.2无关,错误信息是

include/c ++/4.5.2/functional:180:9:错误:必须使用».«或» - > «使用_Tp = void(Foo ::*)(long unsigned int)调用»std :: declval中的指向成员函数,typename std :: add_rvalue_reference <_Tp> :: type = void( Foo :: &&)(long unsigned int)(...)«,例如»(... - > std :: declval with _Tp = void(Foo ::*)(long unsigned int),typename std :: add_rvalue_reference <_Tp> :: type = void(Foo ::*&&)(long unsigned int))(...)«

显然,错误在于旧版本的g ++.通过将方法公开并引入以下帮助函数,可以解决此问题:

void barHelp(Foo* foo, const size_t n)
{
    foo->bar(n);
}
void Foo:foo()
{
    auto handle = std::async(std::launch::async, barHelp, this, 0);
    handle.get();
}
Run Code Online (Sandbox Code Playgroud)

但是,公开方法并不是最好的设计决策.有没有其他方法可以解决此问题而无需更改编译器并将方法保持为私有?

Jos*_*eld 12

问题似乎是它对成员函数不会很好.也许您可以std::bind先将成员函数发送到您的对象,然后再将其传递给std::async:

auto func = std::bind(&Foo::bar, this, std::placeholders::_1);
auto handle = std::async(std::launch::async, func, 0);
Run Code Online (Sandbox Code Playgroud)


fio*_*ing 5

我更喜欢 lambda 而不是 std::bind

#include <iostream>
#include <future>

class Foo
{
private:
    void bar(const size_t)
    {}
public:
    void foo()
    {
        auto handle = std::async(std::launch::async, [this](){
            this->bar(0);
        });
        handle.get();
    }
};

int main()
{
    Foo foo;
    foo.foo();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

或者,但对我来说不太可读,

        auto handle = std::async(std::launch::async, [this](const size_t num){
            this->bar(num);
        }, 0);
Run Code Online (Sandbox Code Playgroud)