将具有可变参数的输入函数变形为成员函数
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
的方法。
我想做的是设计一个可以异步执行函数的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
的方法。