使用指针指向独立函数

时间:2017-11-02 08:23:00

标签: c++ stl c++14 function-pointers

我尝试使用指向函数的指针(不是指向成员函数的指针)调用std::thread完美转发构造函数(template< class Function, class... Args > explicit thread( Function&& f, Args&&... args );),如下面的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可以解决问题;我想了解问题出现的原因。

3 个答案:

答案 0 :(得分:6)

std::thread存储传递的参数的副本。其中Massimiliano Janes pointed out在调用者的上下文中被评估为临时的。出于所有意图和目的,最好将其视为const对象。

由于x是一个非const引用,它不能绑定到线程提供给它的参数。

如果您希望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();
}

Live Example

实用程序std::ref将动态创建它。

答案 1 :(得分:3)

std :: thread构造函数在调用可调用的完全转发结果之前对其参数执行decay_copy;在你的foo中,你试图将左值引用(int&amp; x)绑定到右值引用(到临时),因此错误;要么采取一个int,一个int const&amp;或者是一个int&amp;&amp;相反(或传递参考包装)。

答案 2 :(得分:2)

StoryTeller's answer之后,lambda可能会提供更明确的方式来表达这一点:

我认为有几种情况:

如果我们确实想在外部范围内传递对<option value="'.$read.'">'.$read.'</option> 的引用:

i

如果foo参考恰好是一个历史性事故:

 auto thd = std::thread([&i]
 {
     foo("bar", i);
 });

在第二种形式中,我们已经对变量 auto thd = std::thread([]() mutable { int i = 1; foo("bar", i); }); 进行了本地化,并降低了它将被读取或写入线程外部(可能是UB)的风险。