Start thread with member function

C++MultithreadingC++11

C++ Problem Overview


I am trying to construct a std::thread with a member function that takes no arguments and returns void. I can't figure out any syntax that works - the compiler complains no matter what. What is the correct way to implement spawn() so that it returns a std::thread that executes test()?

#include <thread>
class blub {
  void test() {
  }
public:
  std::thread spawn() {
    return { test };
  }
};

C++ Solutions


Solution 1 - C++

#include <thread>
#include <iostream>

class bar {
public:
  void foo() {
    std::cout << "hello from member function" << std::endl;
  }
};

int main()
{
  std::thread t(&bar::foo, bar());
  t.join();
}

EDIT: Accounting your edit, you have to do it like this:

  std::thread spawn() {
    return std::thread(&blub::test, this);
  }

UPDATE: I want to explain some more points, some of them have also been discussed in the comments.

The syntax described above is defined in terms of the INVOKE definition (§20.8.2.1):

> Define INVOKE (f, t1, t2, ..., tN) as follows: > > - (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is an object of type T or a reference to an object of > type T or a reference to an object of a type derived from T; > - ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is not one of the types described in the previous > item; > - t1.*f when N == 1 and f is a pointer to member data of a class T and t 1 is an object of type T or a
> reference to an object of type T or a reference to an object of a
> type derived from T; > - (*t1).*f when N == 1 and f is a pointer to member data of a class T and t 1 is not one of the types described in the previous item; > - f(t1, t2, ..., tN) in all other cases.


Another general fact which I want to point out is that by default the thread constructor will copy all arguments passed to it. The reason for this is that the arguments may need to outlive the calling thread, copying the arguments guarantees that. Instead, if you want to really pass a reference, you can use a std::reference_wrapper created by std::ref.

std::thread (foo, std::ref(arg1));

By doing this, you are promising that you will take care of guaranteeing that the arguments will still exist when the thread operates on them.


Note that all the things mentioned above can also be applied to std::async and std::bind.

Solution 2 - C++

Since you are using C++11, lambda-expression is a nice&clean solution.

class blub {
    void test() {}
  public:
    std::thread spawn() {
      return std::thread( [this] { this->test(); } );
    }
};

since this-> can be omitted, it could be shorten to:

std::thread( [this] { test(); } )

or just (deprecated)

std::thread( [=] { test(); } )

Solution 3 - C++

Here is a complete example

#include <thread>
#include <iostream>

class Wrapper {
   public:
      void member1() {
          std::cout << "i am member1" << std::endl;
      }
      void member2(const char *arg1, unsigned arg2) {
          std::cout << "i am member2 and my first arg is (" << arg1 << ") and second arg is (" << arg2 << ")" << std::endl;
      }
      std::thread member1Thread() {
          return std::thread([=] { member1(); });
      }
      std::thread member2Thread(const char *arg1, unsigned arg2) {
          return std::thread([=] { member2(arg1, arg2); });
      }
};
int main(int argc, char **argv) {
   Wrapper *w = new Wrapper();
   std::thread tw1 = w->member1Thread();
   std::thread tw2 = w->member2Thread("hello", 100);
   tw1.join();
   tw2.join();
   return 0;
}

Compiling with g++ produces the following result

g++ -Wall -std=c++11 hello.cc -o hello -pthread

i am member1
i am member2 and my first arg is (hello) and second arg is (100)

Solution 4 - C++

@hop5 and @RnMss suggested to use C++11 lambdas, but if you deal with pointers, you can use them directly:

#include <thread>
#include <iostream>

class CFoo {
  public:
    int m_i = 0;
    void bar() {
      ++m_i;
    }
};

int main() {
  CFoo foo;
  std::thread t1(&CFoo::bar, &foo);
  t1.join();
  std::thread t2(&CFoo::bar, &foo);
  t2.join();
  std::cout << foo.m_i << std::endl;
  return 0;
}

outputs

2

Rewritten sample from this answer would be then:

#include <thread>
#include <iostream>

class Wrapper {
  public:
      void member1() {
          std::cout << "i am member1" << std::endl;
      }
      void member2(const char *arg1, unsigned arg2) {
          std::cout << "i am member2 and my first arg is (" << arg1 << ") and second arg is (" << arg2 << ")" << std::endl;
      }
      std::thread member1Thread() {
          return std::thread(&Wrapper::member1, this);
      }
      std::thread member2Thread(const char *arg1, unsigned arg2) {
          return std::thread(&Wrapper::member2, this, arg1, arg2);
      }
};

int main() {
  Wrapper *w = new Wrapper();
  std::thread tw1 = w->member1Thread();
  tw1.join();
  std::thread tw2 = w->member2Thread("hello", 100);
  tw2.join();
  return 0;
}

Solution 5 - C++

Some users have already given their answer and explained it very well.

I would like to add few more things related to thread.

  1. How to work with functor and thread. Please refer to below example.

  2. The thread will make its own copy of the object while passing the object.

     #include<thread>
     #include<Windows.h>
     #include<iostream>
     
     using namespace std;
     
     class CB
     {
     
     public:
     	CB()
     	{
     		cout << "this=" << this << endl;
     	}
     	void operator()();
     };
     
     void CB::operator()()
     {
     	cout << "this=" << this << endl;
     	for (int i = 0; i < 5; i++)
     	{
     		cout << "CB()=" << i << endl;
     		Sleep(1000);
     	}
     }
     
     void main()
     {
     	CB obj;		// please note the address of obj.
     	
     	thread t(obj); // here obj will be passed by value 
                        //i.e. thread will make it own local copy of it.
     					// we can confirm it by matching the address of
                         //object printed in the constructor
     					// and address of the obj printed in the function
     
     	t.join();
     }
    

Another way of achieving the same thing is like:

void main()
{
	thread t((CB()));

	t.join();
}

But if you want to pass the object by reference then use the below syntax:

void main()
{
	CB obj;
	//thread t(obj);
	thread t(std::ref(obj));
	t.join();
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionabergmeierView Question on Stackoverflow
Solution 1 - C++Stephan DollbergView Answer on Stackoverflow
Solution 2 - C++RnMssView Answer on Stackoverflow
Solution 3 - C++hop5View Answer on Stackoverflow
Solution 4 - C++Andrey StarodubtsevView Answer on Stackoverflow
Solution 5 - C++MohitView Answer on Stackoverflow