2015-10-24 62 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我的答案做到這一點。

相關問題