2

I'm new to std::thread and C++11 in general. Trying to toy with the examples from https://en.cppreference.com/w/cpp/thread/thread/thread, I am trying to see if I can spawn a std::thread using a class member function call operator with non-empty argument list as in the code below:

// main.cpp

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

class Foo {
public:

  void operator()( int& i ) {
    std::cout << i << std::endl;
  }
};

int main( int argc, char* argv[] ) {
  Foo f;
  int i = 42;

  std::thread t1( f, i );
  t1.join();

  return 0;
}

The error message is cryptic:

$ g++ --version && g++ ./main.cpp -lpthread && ./a.out
g++ (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

In file included from /usr/include/c++/6/thread:39:0,
                 from ./main.cpp:5:
/usr/include/c++/6/functional: In instantiation of ‘struct std::_Bind_simple<Foo(int)>’:
/usr/include/c++/6/thread:138:26:   required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = Foo&; _Args = {int&}]’
./main.cpp:19:24:   required from here
/usr/include/c++/6/functional:1365:61: error: no type named ‘type’ in ‘class std::result_of<Foo(int)>’
       typedef typename result_of<_Callable(_Args...)>::type result_type;
                                                             ^~~~~~~~~~~
/usr/include/c++/6/functional:1386:9: error: no type named ‘type’ in ‘class std::result_of<Foo(int)>’
         _M_invoke(_Index_tuple<_Indices...>)

In contrast, a empty argument list call operator works fine:

// main.cpp

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

class Foo {
public:

  void operator()() {
    std::cout << 42 << std::endl;
  }
};

int main( int argc, char* argv[] ) {
  Foo f;
  int i = 42;

  std::thread t1( f );
  t1.join();

  return 0;
}
$ g++ --version && g++ ./main.cpp -lpthread && ./a.out
g++ (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

42

Is my first attempt at all feasible - do I just have a syntax error? Is there a way to spawn a std::thread using an object and its non-empty argument list call operator?


I believe this question is distinct from Start thread with member function because this question is specifically about spawning a thread using a member object call operator I'm aware that this can be done with lambdas.

StoneThrow
  • 5,314
  • 4
  • 44
  • 86
  • Use lambda expressions. – Passer By Sep 22 '20 at 03:52
  • 1
    Does this answer your question? [Start thread with member function](https://stackoverflow.com/questions/10673585/start-thread-with-member-function) – Passer By Sep 22 '20 at 03:53
  • Specifically, the second answer. Ignore the first answer. – Passer By Sep 22 '20 at 03:53
  • @PasserBy - I did see similar examples using member _functions_ at cppreference.com -- but I was wanting to learn if this can be pulled off specifically with a _call operator_ - therefore I think this question is distinct from the link you provided. – StoneThrow Sep 22 '20 at 03:57
  • I've retracted my dupe vote, as I feel it's distinct; however it would be worth mentioning _in your question_ that you are aware of that it can be done with a lambda but you're specifically asking about doing so without – Tas Sep 22 '20 at 04:18
  • @Tas - updated. – StoneThrow Sep 22 '20 at 04:23
  • @StoneThrow I had started writing an answer to your recent question when you deleted it. Now that it's deleted I can't post the answer, but I thought it might still be useful to you, so here it is: https://gist.github.com/jtbandes/56477e838b952bff7ff3bd012755209c – jtbandes Sep 23 '20 at 00:29

1 Answers1

3

std::thread doesn't let you pass by reference unless you're explicit because it's an easy source of lifetime issues. Use std::ref to be explicit that you're passing i by reference:

std::thread t1( f, std::ref(i) );

Alternatively, pass by value. Think hard before you pass something to a thread by reference and make sure it's necessary. The variable you pass must outlive its use inside the thread.

chris
  • 60,560
  • 13
  • 143
  • 205
  • Worked -- nice! But why the special protection around passing by reference (I understand variable lifetime issues), when the same doesn't seem to be true about passing by pointer? E.g. to fix my problem, instead of `std::ref`, I changed to passing my argument by pointer - and that worked. – StoneThrow Sep 22 '20 at 04:21
  • 1
    @StoneThrow, Passing by pointer is already explicit—you have the `&` at the callsite to take the address. If you already have a pointer variable that you pass without decoration, hopefully it's well-named anyway. That aside, there's no ready-made `std::reference_wrapper` for pointers. – chris Sep 22 '20 at 04:45