【问题标题】:std::thread wrapper with run method带有运行方法的 std::thread 包装器
【发布时间】:2018-07-11 19:01:02
【问题描述】:

我正在尝试使用 run 方法为 std::thread 编写一个包装器,这将允许线程仅在调用 run 时执行。

       class ThreadRAII_WITHRUN {                                                                                                                                                 

public:                                                                                                                                                                    
enum class DtorAction { join, detach };                                                                                                                                

template< class Function, class... Args >                                                                                                                              
ThreadRAII_WITHRUN(DtorAction a,Function&& f, Args&&... args)                                                                                                          
: action(a)                                                                                                                                                            
, t(std::thread([&](){pro.get_future().wait(); std::forward<Function>(f)(std::forward<Args>(args)...);}))                                                              
{                                                                                                                                                                      
}                                                                                                                                                                      

void run()                                                                                                                                                             
{                                                                                                                                                                      
    pro.set_value();                                                                                                                                                   
}                                                                                                                                                                      

~ThreadRAII_WITHRUN()                                                                                                                                                  
{                                                                                                                                                                      
if (t.joinable()) { // joinability test                                                                                                                                
    if (action == DtorAction::join) {                                                                                                                                  
    t.join();                                                                                                                                                          
    } else {                                                                                                                                                           
    t.detach();                                                                                                                                                        
    }                                                                                                                                                                  
}                                                                                                                                                                      
}                                                                                                                                                                      
ThreadRAII_WITHRUN(ThreadRAII_WITHRUN&&) = default; // support                                                                                                         
ThreadRAII_WITHRUN& operator=(ThreadRAII_WITHRUN&&) = default; // moving                                                                                               
std::thread& get() { return t; }                                                                                                                           

private: // as before                                                                                                                                                      
DtorAction action;                                                                                                                                                     
std::promise<void> pro;                                                                                                                                                
std::thread t;                                                                                                                                                         

};     

此代码使用 gcc6.1.0 编译,但不使用 gcc4.8.5

使用带有 -std=c++11 标志的 gcc4.8.5 我得到以下错误。

g++ -std=c++11 thread.cpp -pthread
thread.cpp: In lambda function:
thread.cpp:74:94: error: parameter packs not expanded with â...â:
  , t(std::thread([&](){pro.get_future().wait(); std::forward<Function>(f)(std::forward<Args>(args)...);}))
                                                                                              ^
thread.cpp:74:94: note:         âargsâ
thread.cpp: In instantiation of âstruct ThreadRAII_WITHRUN::ThreadRAII_WITHRUN(ThreadRAII_WITHRUN::DtorAction, Function&&, Args&& ...) [with Function = threadwithraii_run()::__lambda10; Args = {int}]::__lambda9â:
thread.cpp:74:106:   required from âThreadRAII_WITHRUN::ThreadRAII_WITHRUN(ThreadRAII_WITHRUN::DtorAction, Function&&, Args&& ...) [with Function = threadwithraii_run()::__lambda10; Args = {int}]â
thread.cpp:104:117:   required from here
thread.cpp:74:94: error: using invalid field âThreadRAII_WITHRUN::ThreadRAII_WITHRUN(ThreadRAII_WITHRUN::DtorAction, Function&&, Args&& ...)::__lambda9::__argsâ

有人知道同样的原因吗?

【问题讨论】:

  • GCC 4.8 几乎不支持 C++11,更不支持 C++14。在使用 GCC 4.8 构建时,您还需要添加 -std=c++0x 以启用它支持的 C++11 功能。
  • 用错误信息编辑了问题,我确实为 gcc4.8.5 提供了 -std=c++11 标志

标签: c++11 gcc c++14


【解决方案1】:

有点离题,lambda 通过引用捕获构造函数参数。在调用run 时,这些引用中的部分或全部可能已失效。按值捕获参数可能更安全,例如:

std::thread([=](){ ... })) 
             ^
             |
             capture by value

【讨论】:

  • 谢谢你。但是一旦参数包被捕获为值,它就需要再次作为值传递给函数并且不能完美转发:(
    t(std::thread( [=](){pro.get_future().wait(); f(args...);}))
  • @user8063157 好吧,你可以在这里安全或完美转发,选择一个。
  • 同意。谢谢。
猜你喜欢
  • 2022-10-18
  • 1970-01-01
  • 1970-01-01
  • 2017-06-05
  • 1970-01-01
  • 2014-02-26
  • 2023-04-07
  • 2017-09-07
  • 1970-01-01
相关资源
最近更新 更多