【问题标题】:C++ error in creating threads, static assertion failed: std::thread arguments must be invocable after conversion to rvalues创建线程时出现 C++ 错误,静态断言失败:转换为右值后,std::thread 参数必须是可调用的
【发布时间】:2021-02-20 09:03:42
【问题描述】:

错误信息如下

/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;
}

【问题讨论】:

  • 请发送minimal reproducible example。我们应该能够复制您的代码,并自己重现确切的错误。
  • 我添加了一个最小的可重现示例,希望对您有所帮助
  • 让它std::thread displaytd(displayAction, std::ref(td));
  • 成功了!你能解释一下为什么吗?谢谢!
  • @NNNNNOY displayAction 需要一个非常量引用作为参数。

标签: c++ multithreading c++11 concurrency c++17


【解决方案1】:

lambda 签名需要一个引用。但是,std::thread can't accept a reference:它必须能够将对象复制到它调用的函数中。

解决方案是std::reference_wrapper 及其方便的小包装器std::ref and std::cref

这里是a working example

#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();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-06
    • 2018-09-18
    • 2014-08-06
    • 1970-01-01
    • 2020-02-01
    相关资源
    最近更新 更多