将具有可变参数的输入函数变形为成员函数

warp an input function with variadic-parameter into member function

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

基本设计如下:

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

编译错误是: error C2064: term 的计算结果不是带 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;
}

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

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

您正在尝试将参数传递给从 std::bind 返回的不带任何参数的函数对象。

使用 std::bind 很难做到,因为它需要 std::placeholders 构造 _1_2_3 等,等表示有 _n 个要传递的参数。这将需要一些模板技巧。

更好的选择是使用 lambda 表达式; C++11 的一个特性,你可能正在使用它,就好像你在使用 std::thread,这是另一个 C++11 特性。

以下是使用 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 的方法。