0

I know there exists this question and this one as well. I have gone through both of them and haven't been able to solve my problem. I was able to run examples for class member functions that take zero arguments, but was not able to deduce what the constructor for the thread would look like in case the member function had arguments.

I have a class A. A has a member function f that takes 2 parameters p1 and p2. I have instantiated an object a of class A. I want to call the function f in a thread.

From cppreference.com :

template< class Function, class... Args > 
explicit thread( Function&& f, Args&&... args );

is how I must write the constructor.

I am having trouble deciphering the above definition. How can I call a.f(p1,p2) defined as

void A::f(int p1, int p2)

in a thread ?

Community
  • 1
  • 1
Chani
  • 5,055
  • 15
  • 57
  • 92
  • Can you explain the meaning of the definition `template< class Function, class... Args > explicit thread( Function&& f, Args&&... args );`. may be then I can think how a lambda can be used to do it. – Chani Jul 20 '14 at 08:06
  • Roughly, `thread ([&a] (q1, q2) { a.f (q1, q2); }, p1, p2);` – JohnB Jul 20 '14 at 08:07
  • `Function` stands for a function object, that you can create in various ways, a lambda object is a good way to do it. – user1095108 Jul 20 '14 at 08:08
  • @T.C. Does `&A::f, a` together define the function object ? – Chani Jul 20 '14 at 08:12
  • @T.C. The difference is that your version makes a copy of `a`. – juanchopanza Jul 20 '14 at 08:13
  • @T.C. That did't work. I don't know why. Got this error : `/usr/include/c++/4.8/functional:1727:9: error: no type named ‘type’ in ‘class std::result_of(std::reference_wrapper, int)>’ _M_invoke(_Index_tuple<_Indices...>) ^ ` – Chani Jul 20 '14 at 08:15
  • @Wildling Yeah, I just tested that, `reference_wrapper` don't work as the `this` argument if you pass a pointer-to-member. To pass by ref, use `std::thread t(&A::f, &a, p1, p2);`. To pass by value, use `std::thread t(&A::f, a, p1, p2);` – T.C. Jul 20 '14 at 08:17
  • @Wildling No, that is a special case. – user1095108 Jul 20 '14 at 08:22
  • @T.C. Yeah, that works. Can you please explain how. I mean the function definition of the `std::thread` mentions only two parameters - the function object and the parameters to the function to be run. But we are passing 3 - the function object, the object and the parameters. What am I missing here ? – Chani Jul 20 '14 at 08:22
  • @user1095108 Can you please tell me what such special cases are called; so that I might look them up ? – Chani Jul 20 '14 at 08:23
  • @Wildling Member functions have an implicit first parameter for `this`. The `std::thread` constructor maps the second parameter to that. – juanchopanza Jul 20 '14 at 08:35
  • @Wildling If you read the cppreference page you link to, it describes exactly how the function is called in various cases. The applicable case here is the paragraph starting with "If f is pointer to a member function of class T". – T.C. Jul 20 '14 at 08:36
  • Another solution: int p1, p2; // assuming you have integer args A obj; std::function func = std::bind(&A::f, p1, p2); std::thread thd{func}; – themoondothshine Jul 20 '14 at 16:42

1 Answers1

7

Simply pass the arguments:

std::thread t(&A::f, &bar, p1, p2);
t.join();

Note: Notice that we are passing the address of your bar object, otherwise the thread constructor would copy your object. By doing this you have to guarantee that your object outlives your thread. Note, that the same is true for the other arguments. In case of the arguments you can simply use std::ref.

In general, as mentioned in my other post, the std::thread constructor 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.
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
Stephan Dollberg
  • 32,985
  • 16
  • 81
  • 107