C ++:如何在复杂的模板类中指定线程函数?

时间:2017-04-22 11:18:06

标签: c++ multithreading templates reference

最小化代码如下。目标是使用模板类中的C ++标准线程库并行复制数据。 Source的对象必须作为参考传输,因为我需要使用C ++的多态特性。数据类型可以是各种复杂对象,而不是最小化代码中的int。编译错误是

  

错误C3867:' Array :: Thread&#39 ;:非标准语法;使用'&'至   创建指向成员的指针

我已经从互联网上阅读了很多相关的主题但是它们太简单了。我也尝试使用functor来指定线程工作器函数但是失败了。那么,如何解决这个复杂模板情况下的问题(你可以使用仿函数)?我正在使用Visual Studio 2015,但我认为Linux上会出现类似的错误消息。非常感谢你的帮助。

#include <thread>
#include <iostream>
#include <vector>
using namespace std;

template < typename U >
class Source {
public:
    Source(U data) : data(data) {}
    U Get() { return data; }
private:
    U data;
};

template < typename U >
class Array {
public:
    Array(U data) {
        for (int i = 0; i < 10; i++)
            t[i] = data;
    }
    void Thread(int i, Source<U>& source) {
        t[i] = source.Get();
    }
    void ThreadsWrapper(Source<U>& source) {
        vector<thread> threads;
        for (int i = 0; i < 10; i++)
            threads.push_back(thread(Thread, i, ref(source)));

        for (auto & t : threads)
            t.join();
    }
private:
    U t[10];
};

int main()
{
    Source<int> c(7);
    Array<int> a(2);
    a.ThreadsWrapper(c);
}

2 个答案:

答案 0 :(得分:2)

只需使用lambda:

threads.push_back(thread([&]{ Thread(i, source); }));

这可以避免使用std::bindstd::ref或类似构造的所有可能难以阅读的变通方法。

您的原始错误消息是由于您间接尝试在没有Thread实例的情况下调用Array而导致的。您试图使用std::thread函数构造Thread,但没有告诉它应该在this上调用它。

答案 1 :(得分:2)

问题是&#34;简单地说&#34;句法。你需要的是:

threads.push_back(std::thread(&Array::Thread, this, i, ref(source)));

第一个问题是Thread是成员函数的名称。要获取其地址,您需要&Array::Thread。那个(或多或少)错误消息告诉你的内容。第二个问题是必须在对象上调用成员函数,这就是在创建线程时必须传递this的原因。