c++ - 创建线程时出现 C++ 错误,静态断言失败:转换为右值后,std::thread 参数必须是可调用的
问题描述
错误信息如下
/usr/include/c++/9/thread: In instantiation of ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(DisplayObject&); _Args = {DisplayObject&}; <template-parameter-1-3> = void]’:
farmville.cpp:242:53: required from here
/usr/include/c++/9/thread:120:44: error: static assertion failed: std::thread arguments must be invocable after conversion to rvalues
120 | typename decay<_Args>::type...>::value,
| ^~~~~
/usr/include/c++/9/thread: In instantiation of ‘struct std::thread::_Invoker<std::tuple<void (*)(DisplayObject&), DisplayObject> >’:
/usr/include/c++/9/thread:131:22: required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(DisplayObject&); _Args = {DisplayObject&}; <template-parameter-1-3> = void]’
farmville.cpp:242:53: required from here
/usr/include/c++/9/thread:243:4: error: no type named ‘type’ in ‘struct std::thread::_Invoker<std::tuple<void (*)(DisplayObject&), DisplayObject> >::__result<std::tuple<void (*)(DisplayObject&), DisplayObject> >’
243 | _M_invoke(_Index_tuple<_Ind...>)
| ^~~~~~~~~
/usr/include/c++/9/thread:247:2: error: no type named ‘type’ in ‘struct std::thread::_Invoker<std::tuple<void (*)(DisplayObject&), DisplayObject> >::__result<std::tuple<void (*)(DisplayObject&), DisplayObject> >’
247 | operator()()
我要做的是创建一个控制对象的线程。所以我创建了一个可以控制对象的函数,并使用该函数创建一个线程。
void chickenAction(DisplayObject &chicken){
int x = std::max(1, chicken.current_x + (1 + std::rand()) % 10 - 5);
int y = std::max(1, chicken.current_y + (1 + std::rand()) % 10 - 5);
chicken.draw(y, x);
chicken.moveto(y, x);
}
下面是创建线程的代码,chicken1 是一个对象:
std::thread chicken1Thread(chickenAction, chicken1);
chicken1Thread.join();
我认为下面的代码可以重复错误
#include <iostream>
#include <unistd.h>
#include <thread>
class DisplayThread {
public:
int size;
DisplayThread(){};
void changeSize(int x) {
size = x;
}
};
void displayAction(DisplayThread &td){
td.changeSize(1);
}
int main() {
DisplayThread td;
std::thread displaytd(displayAction, td);
displaytd.join();
return 0;
}
解决方案
lambda 签名需要一个引用。但是,std::thread
不能接受引用:它必须能够将对象复制到它调用的函数中。
解决方案是std::reference_wrapper
及其方便的小包装器std::ref
和std::cref
.
这是一个工作示例:
#include <thread> // std::thread
#include <functional> // std::ref
void foo() {
int i_ = 0;
auto thread_func = [](int &i) {
return i+42;
};
// assertion failed: std::thread arguments must be invocable after conversion to rvalues
// std::thread t{thread_func, i_};
// OK!
std::thread t{thread_func, std::ref(i_)};
t.join();
}
推荐阅读
- html - 为什么这个 svg 中有额外的空白?
- c# - 为什么代码覆盖在 ReSharper 中不起作用?
- php - 在 WooCommerce 中验证电话号码
- python - 有没有办法更改函数中的全局变量(如计数器),然后让它保留该值以在另一个函数中使用?
- javascript - 如何使用ajax c#从控制器获取数据
- react-native - React Native Schedule 本地通知最佳实践
- java - 为什么在使用 Eclipse 调用 PDDocument 时出现 java.lang.NoClassDefFoundError
- docker - 在 VM 中使用 Docker 容器进行远程调试
- c# - 仅当数据从以前的值更改时如何存储数据?
- c - 在二维字符数组中搜索单词