关于C++:std::async成员函数的异步调用

std::async call of member function

考虑以下类别:

1
2
3
4
5
6
7
class Foo
{
   private:
      void bar(const size_t);
   public:
      void foo();
};

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

1
2
3
4
5
void Foo:foo()
{
    auto handle = std::async(std::launch::async, &Foo::bar, this, 0);
    handle.get();
}

这对于G++-4.6.3是完美的,但对于G++-4.5.2则不是,错误消息是

include/c++/4.5.2/functional:180:9: Error: must use ?.? or ?->? to call pointer-to-member function in ?std::declval with _Tp = void (Foo::*)(long unsigned int), typename std::add_rvalue_reference<_Tp>::type = void (Foo::&&)(long unsigned int) (...)?, e.g. ?(... -> std::declval with _Tp = void (Foo::*)(long unsigned int), typename std::add_rvalue_reference<_Tp>::type = void (Foo::*&&)(long unsigned int)) (...)?

所以很明显,这个错误存在于G++的旧版本中。可以通过公开方法并引入以下助手函数来解决此问题:

1
2
3
4
5
6
7
8
9
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();
}

然而,公开方法并不是最佳的设计决策。在不更改编译器和保持方法私有的情况下,有没有其他方法来解决这个问题?


问题似乎是它不能很好地处理成员函数。也许在将成员函数传递给std::async之前,您可以先将该成员函数std::bind传递给您的对象:

1
2
auto func = std::bind(&Foo::bar, this, std::placeholders::_1);
auto handle = std::async(std::launch::async, func, 0);