使用引用参数的C ++线程编译失败 [英] C++ Thread taking reference argument failed compile

查看:208
本文介绍了使用引用参数的C ++线程编译失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

#include<iostream>
#include<thread>
using namespace std;

void f1(double& ret) {
   ret=5.;
}

int main() {
   double ret=0.;
   thread t1(f1, ret);
   t1.join();
   cout << "ret=" << ret << endl;
}

以上代码使用以下错误消息

g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
In file included from /usr/local/include/c++/5.3.0/thread:39:0,
                 from main.cpp:2:
/usr/local/include/c++/5.3.0/functional: In instantiation of 'struct std::_Bind_simple<void (*(double))(double&)>':
/usr/local/include/c++/5.3.0/thread:137:59:   required from 'std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(double&); _Args = {double&}]'
main.cpp:11:21:   required from here
/usr/local/include/c++/5.3.0/functional:1505:61: error: no type named 'type' in 'class std::result_of<void (*(double))(double&)>'
       typedef typename result_of<_Callable(_Args...)>::type result_type;
                                                             ^
/usr/local/include/c++/5.3.0/functional:1526:9: error: no type named 'type' in 'class std::result_of<void (*(double))(double&)>'
         _M_invoke(_Index_tuple<_Indices...>)
         ^

我知道我可以使用 std :: ref()传递参数。但是,如果我按值传递,为什么会出错,因为 thread 应该只按 value 复制参数,然后将存储在线程中的某些对象传递给绑定带有功能 f1 的引用参数。

I understand that I can use std::ref() to pass the argument. But if I pass by value, why is it an error since thread should just copy the argument by value and pass some object stored inside thread to bind with the reference argument of function f1.

我觉得如果我能理解这 result_of 正在执行,为什么会出现错误,我可以更好地理解原因。那么有人可以指导我解决错误消息吗?特别是 std :: _ Bind_simple< void(*(double))(double&)> std :: result_of< void(* (double))(double&)>

I feel that if I can understand what this result_of is doing and why it is giving error, I can better understand the reason. So could anyone walk me through the error msg? Especially the meanings of std::_Bind_simple<void (*(double))(double&)> and std::result_of<void (*(double))(double&)>.

编辑:我知道如果传递一个值,则该线程将仅对副本起作用,并且在线程返回后无效。那不是我的问题。我想知道为什么现在给错误了,但是却没有给SO上的其他帖子带来错误,如下所示:指针与作为线程参数的引用之间的差异

EDIT: I know if I pass a value, the thread will only work on the copy and has no effect after the thread returns. That is not my concern. I want to know why it is giving error now, but it was not giving error to other posts on SO like the following:Difference between pointer and reference as thread parameter

推荐答案


我知道如果我传递一个值,则该线程将仅在副本上起作用,并且在线程返回后无效。

I know if I pass a value, the thread will only work on the copy and has no effect after the thread returns.

不,那是不正确的。该代码不应默默地进行复制并在该副本上工作,该标准表示该代码甚至都不能编译。

No, that's not correct. The code should not silently make a copy and work on the copy, the standard says it must not even compile.

该标准要求复制被调用函数的参数。 (进入由C ++运行时管理的存储),然后副本作为右值转发。因此,在您的示例中, f1 传递了一个 double 类型的右值和一个 double&类型的参数; 不能绑定到该右值。

The standard requires that the arguments to the called function are copied (into storage managed by the C++ runtime) and then the copies are forwarded as rvalues. So in your example f1 gets passed an rvalue of type double and the parameter of type double& cannot bind to that rvalue.

该标准要求这样做的原因是,因此不会出现静默复制和数据丢失:if函数需要可修改的引用,除非您使用 reference_wrapper 显式传递引用,否则它将不会编译。

The reason the standard requires that is so there is no silent copying and loss of data: if the function requires a modifiable reference then it won't compile unless you pass a reference explicitly using a reference_wrapper.

编译器您遇到的错误涉及 result_of ,因为这就是我让GCC的 std :: thread 检查是否可以使用提供的参数。我使用 result_of< decltype(& f1)(double)> 检查函数指针& f1 (类型为 void(*)(double&))可以使用类型为 double 的右值来调用。无法使用该类型的参数进行调用,因此未定义嵌套类型 result_of< decltype(& f1)(double)>:type ,因此编译器会说:

The compiler error you get involves result_of because that's how I made GCC's std::thread check if the function can be called with the supplied arguments. I use result_of<decltype(&f1)(double)> to check if the function pointer &f1 (which is of type void(*)(double&)) can be called with an rvalue of type double. It can't be called with an argument of that type, so the nested type result_of<decltype(&f1)(double)>::type is not defined, so the compiler says:

error: no type named 'type' in 'class std::result_of<void (*(double))(double&)>'

该错误有点令人困惑,因为C ++声明符规则意味着 decltype(& f1)(double)显示为 void(*(double))(double&)

The error is a bit confusing because the C++ declarator rules mean that decltype(&f1)(double) gets displayed as void(*(double))(double&).


这不是我的问题。我想知道为什么它现在会出错,但是并没有给其他帖子上的错误

That is not my concern. I want to know why it is giving error now, but it was not giving error to other posts on SO

这些帖子使用了旧的C ++ 11之前版本或不合格的编译器,不符合C ++ 11标准的要求,并且错误地编译了代码。

Those posts were using an old pre-C++11 or non-conforming compiler which didn't meet the requirements of the C++11 standard and incorrectly compiled the code.

这篇关于使用引用参数的C ++线程编译失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆