Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invoking std::thread with pointer to freestanding function

I tried to invoke std::thread perfect forwarding constructor (template< class Function, class... Args > explicit thread( Function&& f, Args&&... args );) with a pointer to function (NOT a pointer to member function), as shown in the following M(N)WE:

#include <thread>
#include <string>

static void foo(std::string query, int & x)
{
  while(true);
}

int main() {
 int i = 1;
 auto thd = std::thread(&foo, std::string("bar"), i);
 thd.join();
}

Live demo: https://godbolt.org/g/Cwi6wd

Why does the code not compile on GCC, Clang and MSVC, complaining about a missing overload of invoke (or similar names)? A function argument is a pointer to a function, so it should be a Callable, right?

Please note: I know that using a lambda would solve the problem; I want to understand why the problem arises.

like image 320
Astrinus Avatar asked Nov 02 '17 08:11

Astrinus


1 Answers

std::thread stores copies of the arguments it is passed. Which as Massimiliano Janes pointed out, is evaluated in the context of the caller to a temporary. For all intents and purposes, it's better to consider it as a const object.

Since x is a non-const reference, it cannot bind to the argument being fed to it by the thread.

If you want x to refer to i, you need to use std::reference_wrapper.

#include <thread>
#include <string>
#include <functional>

static void foo(std::string , int & )
{
  while(true);
}

int main() {
 int i = 1;
 auto thd = std::thread(foo, std::string("bar"), std::ref(i));
 thd.join();
}

Live Example

The utility std::ref will create it on the fly.

like image 145
StoryTeller - Unslander Monica Avatar answered Oct 02 '22 18:10

StoryTeller - Unslander Monica