28

I want to be able to define a class with some data members, and a function which has access to those data members, which are to be private.

I then want a public function, which creates some threads, which operate on the data members of the class. I am having some trouble getting my code to compile.

Don't worry about mutex or data protection, this isn't going to be a problem, since this is just some example code for testing.

class foo {
    public:
    void make_foo_func_threads();

    private:
    void foo_func();

    char private_data;
    std::vector<std::thread> some_threads;
}

void foo::foo_func() {
    while(1) {
        private_data = 'A';
    }
}

void foo::make_foo_func_thread() {
    for(...) some_threads.push_back(std::thread(foo_func));
    for(...) some_threads.join();
}

The compiler is giving me the error:

'no matching call to std::thread::thread()'

Apparently there is 'no known conversion for argument 1 from <unresolved overloaded function type> to void (foo::*&&)'.

Erm, yeah, I have no idea what that means apart from the compiler is having trouble understanding how to resolve foo_func - I think.

How can I help the compiler understand what I am trying to do, so it won't bother me with any more errors. No doubt the code I have written is not legal, and if that is the case could someone explain why that is the case to me. Thanks!

hmjd
  • 120,187
  • 20
  • 207
  • 252
FreelanceConsultant
  • 13,167
  • 27
  • 115
  • 225

1 Answers1

37

foo_func is a (non-static) member function, and it needs an instance of foo on which to operate. This instance must be provided to the thread constructor. If you refer to the std::thread::thread reference page it explains what code is executed in the new thread. The relevant point is that which refers to f being a pointer to member function:

  • If f is pointer to a member function of class T, then it is called. The return value is ignored. Effectively, the following code is executed:
    • (t1.*f)(t2, ..., tN) if the type of t1 is either T, reference to T or reference to type derived from T.
    • ((*t1).*f)(t2, ..., tN) otherwise.

so it is clear that the instance is required.

Change to:

for(...) some_threads.push_back(std::thread(&foo::foo_func, this));

Simple example:

#include <iostream>
#include <thread>
#include <vector>

class foo
{
public:
    void make_foo_func_threads()
    {
        for (int i = 0; i < 5; ++i)
            some_threads.push_back(std::thread(&foo::foo_func, this));
        for (auto& t: some_threads) t.join();
    }

private:
    void foo_func() { std::cout << "Hello\n"; }
    std::vector<std::thread> some_threads;
};

int main()
{
    foo f;
    f.make_foo_func_threads();
}
hmjd
  • 120,187
  • 20
  • 207
  • 252
  • Okay, that's great! One problem though, my program drops out of the bottom of main, even though there is supposed to be an infinite loop running. thread.join() doesn't seem to be waiting for the threads to join! – FreelanceConsultant Jul 04 '13 at 14:46
  • 1
    @EdwardBird, could you post the full program to stacked-crooked or similar and post a link? Or better, post another question to get other people's contribution (and this answer, and the other, have addressed the question as posted). – hmjd Jul 04 '13 at 14:48
  • 3
    Oops, no my bad I didn't put f.make_foo_func_threads(); in main! Sorry about that, it works fine everybody DONT PANIC! >. – FreelanceConsultant Jul 04 '13 at 14:49
  • Thanks this answer save my time, but a simple question appeard in my mind, why we use pointer to class or `this` in thread? my means =`some_threads.push_back(std::thread(&foo::foo_func, this));` – Saeed Masoomi Oct 21 '18 at 13:09