user5280911
user5280911

Reputation: 763

C++: how to specify thread function in a complex template class?

The minimized code is as follows. The goal is to copy data in parallel using C++ standard threading library from a template class. The object of the Source must be transmitted as a reference because I need to use polymorphism feature of C++. The data type can be various complex object instead of int in the minimized code. The compile error is

error C3867: 'Array::Thread': non-standard syntax; use '&' to create a pointer to member

I have read many related threads from internet but they are all too simple to apply. I also tried using functor to specify the thread worker function but failed. So, how to fix the issue in this complex template situation (you can use functor)? I am using Visual Studio 2015 but I think similar error message would appear on Linux. Thanks a lot for your help.

#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);
}

Upvotes: 0

Views: 220

Answers (2)

Pete Becker
Pete Becker

Reputation: 76523

The problem is "simply" syntax. What you need is this:

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

The first problem is that Thread is the name of a member function. To take its address you need &Array::Thread. That's (more or less) what the error message is telling you. The second problem is that member functions have to be called on objects, which is why you have to pass this when you create the thread.

Upvotes: 2

Christian Hackl
Christian Hackl

Reputation: 27548

Just use a lambda:

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

This avoids all potentially hard-to-read workarounds with std::bind, std::ref or similar constructs.

Your original error message was caused by the fact that you indirectly tried to call Thread without an instance of Array. You attempted to construct the std::thread with the Thread function, but failed to tell it that it should be called on this.

Upvotes: 2

Related Questions