使用variadic-parameter将输入函数转换为成员函数

时间:2015-10-24 10:44:48

标签: c++ multithreading c++11 variadic-templates

我想要做的是设计一个可以异步执行函数的类。我需要在成员函数中对其进行扭曲,因为我想知道它是否完成。

基本设计如下:

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的基础。

在看到您的评论和答案之前

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

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

1 个答案:

答案 0 :(得分:1)

嗯,你有一些可用的骨架。但是如果您查看错误的来源,错误就非常明显了:

  <ListView.ItemTemplate>
        <DataTemplate>
          <WrapPanel>
             ...
             <TextBlock Text="Instructor: " />
             <TextBlock Text="{Binding instructor.name}" FontWeight="Bold" />
          </WrapPanel>
        </DataTemplate>
  </ListView.ItemTemplate>

您正在尝试将参数传递给从std::thread(std::bind(member_fn, this), fn, args...) 返回的不带任何参数的函数对象。

使用std::bind要做的事情非常困难,因为它需要std::bind构造std::placeholders_1_2等等表示有_3个args要传递。这需要一些模板技巧。

更好的选择是使用lambda表达式; C ++ 11的一个功能,您可能正在使用它,就好像您使用_n这是另一个C ++ 11功能。

以下是使用lambdas的方法:

std::thread

我可以使用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; } 添加一种方法来做到这一点。