使用指向独立函数的指针调用 std::thread
Invoking std::thread with pointer to freestanding function
我尝试调用 std::thread
完美转发构造函数 (template< class Function, class... Args > explicit thread( Function&& f, Args&&... args );
) 并带有指向函数的指针(不是指向 member 函数的指针),如图所示在以下 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();
}
现场演示:https://godbolt.org/g/Cwi6wd
为什么代码无法在 GCC、Clang 和 MSVC 上编译,抱怨缺少 invoke
(或类似名称)的重载?
函数参数是指向函数的指针,所以它应该是一个Callable
,对吗?
请注意:我知道使用 lambda 可以解决问题;我想了解为什么会出现这个问题。
std::thread
存储传递给它的参数的副本。作为 ,在临时调用者的上下文中进行评估。出于所有意图和目的,最好将其视为 const 对象。
由于 x
是一个非常量引用,它不能绑定到线程提供给它的参数。
如果要x
引用i
,需要使用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();
}
实用程序 std::ref
将即时创建它。
std::thread 构造函数在调用可调用对象之前对其参数执行 decay_copy——将结果完美转发给它;在您的 foo 中,您正试图将左值引用 (int& x) 绑定到右值引用(临时值),因此出现错误;取而代之的是 int、int const& 或 int&&(或传递引用包装器)。
继 之后,lambda 可能提供更清晰的表达方式:
我认为有两种情况:
如果我们真的想在外部范围内传递对 i
的引用:
auto thd = std::thread([&i]
{
foo("bar", i);
});
如果 foo 引用恰好是一个历史事故:
auto thd = std::thread([]() mutable
{
int i = 1;
foo("bar", i);
});
在第二种形式中,我们对变量进行了本地化 i
并降低了它在线程外(即 UB)被读取或写入的风险。
我尝试调用 std::thread
完美转发构造函数 (template< class Function, class... Args > explicit thread( Function&& f, Args&&... args );
) 并带有指向函数的指针(不是指向 member 函数的指针),如图所示在以下 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();
}
现场演示:https://godbolt.org/g/Cwi6wd
为什么代码无法在 GCC、Clang 和 MSVC 上编译,抱怨缺少 invoke
(或类似名称)的重载?
函数参数是指向函数的指针,所以它应该是一个Callable
,对吗?
请注意:我知道使用 lambda 可以解决问题;我想了解为什么会出现这个问题。
std::thread
存储传递给它的参数的副本。作为
由于 x
是一个非常量引用,它不能绑定到线程提供给它的参数。
如果要x
引用i
,需要使用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();
}
实用程序 std::ref
将即时创建它。
std::thread 构造函数在调用可调用对象之前对其参数执行 decay_copy——将结果完美转发给它;在您的 foo 中,您正试图将左值引用 (int& x) 绑定到右值引用(临时值),因此出现错误;取而代之的是 int、int const& 或 int&&(或传递引用包装器)。
继
我认为有两种情况:
如果我们真的想在外部范围内传递对 i
的引用:
auto thd = std::thread([&i]
{
foo("bar", i);
});
如果 foo 引用恰好是一个历史事故:
auto thd = std::thread([]() mutable
{
int i = 1;
foo("bar", i);
});
在第二种形式中,我们对变量进行了本地化 i
并降低了它在线程外(即 UB)被读取或写入的风险。