在抽象基础 class 中使用 c++11 的 std::async

Using c++11's std::async inside an abstract base class

为什么像这样的线程不能在抽象基础中工作 class?我试图为从这个基础 class 派生的用户抽象出所有多线程细节。我不明白为什么它说 "no type named 'type'" 当我清楚地写 callbackSquare returns 类型 int.

#include <iostream>
#include <future>
#include <vector>

class ABC{
public:
    std::vector<std::future<int> > m_results;
    ABC(){};
    ~ABC(){};
    virtual int callbackSquare(int& a) = 0;
    void doStuffWithCallBack();
};

void ABC::doStuffWithCallBack(){
    for(int i = 0; i < 10; ++i)
        m_results.push_back(std::async(&ABC::callbackSquare, this, i));

    for(int j = 0; j < 10; ++j)
        std::cout << m_results[j].get() << "\n";
}

class Derived : public ABC {
    Derived() : ABC() {};
    ~Derived(){};
    int callbackSquare(int& a) {return a * a;};
};

int main(int argc, char **argv)
{

    std::cout << "testing\n";

    return 0;
}

我遇到的奇怪错误是:

/usr/include/c++/5/future:1709:67:   required from 'std::future<typename std::result_of<_Functor(_ArgTypes ...)>::type> std::async(std::launch, _Fn&&, _Args&& ...) [with _Fn = int (ABC::*)(int&); _Args = {ABC*, int&}; typename std::result_of<_Functor(_ArgTypes ...)>::type = int]'
/usr/include/c++/5/future:1725:19:   required from 'std::future<typename std::result_of<_Functor(_ArgTypes ...)>::type> std::async(_Fn&&, _Args&& ...) [with _Fn = int (ABC::*)(int&); _Args = {ABC*, int&}; typename std::result_of<_Functor(_ArgTypes ...)>::type = int]'
/home/taylor/Documents/ssmworkspace/callbacktest/main.cpp:16:69:   required from here
/usr/include/c++/5/functional:1505:61: error: no type named 'type' in 'class std::result_of<std::_Mem_fn<int (ABC::*)(int&)>(ABC*, int)>'
       typedef typename result_of<_Callable(_Args...)>::type result_type;
                                                             ^
/usr/include/c++/5/functional:1526:9: error: no type named 'type' in 'class std::result_of<std::_Mem_fn<int (ABC::*)(int&)>(ABC*, int)>'
         _M_invoke(_Index_tuple<_Indices...>)

您的问题可以用任何接受引用的函数重现:

#include <future>

int f(int& a)
{
    return a * a;
}

int main()
{
    int i = 42;
    auto r = std::async(f, i);
}

在代码中接受引用是有风险的,因为变量 将被循环迭代修改 ,从而造成数据竞争,因为被调用函数也访问该变量。

更改函数以按值接受输入参数,或者通过传递 std::ref(i)std::cref(i) 调用 std::async(如果函数接受 const 引用)风险。