2015-10-24 59 views
-1

我想要做的是设计一个可以异步执行函数的类。我需要在成员函数中对它进行变形,因为我想知道它是否完成。使用variadic参数将输入函数转换为成员函数

的基本设计如下:

struct SelectionAsynMission 
{ 
    template<typename Function, typename...Args> 
    void start(Function && f, Args&&...a) 
    { 
     // compiler failed here 
     thread_.swap(thread(std::bind(&SelectionAsynMission::execute_warp<Function, Args ...>, this), f,std::forward<Args>(a)...)); 
     //thread_.swap(std::thread(f, std::forward<Args>(a)...)); no warp work fine 
     thread_.detach(); 
    } 
    template<typename Function, typename...Args> 
    void execute_warp(Function && f, Args&& ... a) 
    { 
     thread_complete_ = false;  
     f(std::forward<Args>(a)...); 
     thread_complete_ = true; 
    } 
    void join(); 
    atomic<bool> thread_complete_; // Use atomic to tell the main thread whether it is complete. 
    thread thread_; 
}; 

编译错误是: 错误C2064:术语不计算为服用1个参数

所以对于设计的任何建议,以满足功能要求 或有关解决编译错误的想法会有所帮助。


谢谢你的帮助,我太笨了,忘记了std :: bind的基本。

之前看到您的意见和答案

我曾尝试另一种方式来做到这一点。我使用异步来转换函数,而不是原子,我使用未来状态来确定作业是否完成。我不确定哪些花费更多时间,阅读原子或未来状态,但未来状态似乎更容易。

template<class Function, class...Args> 
void start(Function && f, Args&... a) 
{ 
    // start the function with async 
    future_node_ = std::async(std::launch::async,f,std::forward<Args&>(a)...); 
} 

bool iscomplete() 
{ 
    // wait for zero time to get status. 
    auto status = future_node_.wait_for(std::chrono::nanoseconds(0)); 
    // determine whether the job is done 
    return status == std::future_status::ready; 
} 
+0

std :: bind的结果没有带任何参数(但你提供了一些参数),并且绑定本身没有意义,因为你声明了参数应该进入但没有指定它们。我不认为在variadic模板中使用std :: bind有一个令人愉快的方式,并建议使用可变lambda代替。 –

+1

'参数&... a {'ehm –

+0

无法编译的行由一堆不同的嵌套语句组成,这些语句中的哪些完全失败?为了清晰起见,将每个移动到一个单独的行并将结果存储在临时文件中。另外,请缩进您的代码。这就是说,为什么你将线程存储在一个成员变量中,但分离线程?这似乎有点反作用。顺便说一句:在启动线程之前,您需要将'thread_complete'设置为false,否则您不知道线程是否尚未设置或者它是否已设置为true。 –

回答

1

那么,你有一种有用的骨架。

std::thread(std::bind(member_fn, this), fn, args...) 

你试图参数传递给函数对象从std::bind不带任何参数返回:但如果你看看这里的错误是来自错误是很明显的。

你想要的是相当困难的使用std::bind做的,因为它需要std::placeholders结构_1_2_3,等,等信号,有很多_n ARGS传递。这需要一些模板诡计。

更好的选择是使用lambda表达式; C++ 11的一个特性,您可能正在使用它看起来好像使用了另一个C++ 11功能std::thread

下面介绍如何使用lambda表达式来做到这一点:

class myclass{ 
    template<typename Func, typename ... Args> 
    void start(Func &&f, Args &&... args){ 
     m_thread.swap(std::thread{ 
      [this](Func &&f, Args &&... uargs){ 
       this->execute_warp(std::forward<Func>(f), std::forward<Args>(uargs)...); 
      }, 
      std::forward<Func>(f), std::forward<Args>(args)... 
     }); 
     m_thread.detach(); 
    } 

    template<typename Func, typename ... Args> 
    void execute_warp(Func &&f, Args &&... args){ 
     m_thread_done = false; 
     f(std::forward<Args>(args)...); 
     m_thread_done = true; 
    } 

    void join(){ 
     while(!m_thread_done.load(std::memory_order_relaxed)){} 
    } 

    std::atomic<bool> m_thread_done; 
    std::thread m_thread; 
} 

而且我想补充的方式使用std::bind我的答案做到这一点。

相关问题