我希望有一个包装线程函数,即一个由线程执行的函数,它可以做一些额外的事情,然后调用用户函数。
template<class F, class... Args>
void wrapper(F&& user_function, Args&&... args) {
// do some extra stuff
user_function(args); // maybe I need to forward args
// do some extra stuff
}好的,这可能是一个很好的包装器,所以我需要一个使用这个包装函数并允许用户生成自己的线程的管理器:
class ThreadManager {
public:
template<class F, class... Args>
std::thread newThread(F&& f, Args&&... args) {
return std::thread(thread_wrapper<F,Args...>, std::forward<F>(f), std::forward<Args>(args)...);
}
};这样,线程管理器就应该生成一个使用包装器函数的线程,而包装器函数又会完成额外的工作并调用用户函数。
但是编译器现在说:试图使用已删除的函数.。
错误出现在线程头中:
template <class _Fp, class ..._Args, size_t ..._Indices>
inline _LIBCPP_INLINE_VISIBILITY
void
__thread_execute(tuple<_Fp, _Args...>& __t, __tuple_indices<_Indices...>)
{
__invoke(_VSTD::move(_VSTD::get<0>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...);
}我错过了什么/做错了什么?
编辑
使用测试:
void foo(int i) {
std::cout << "foo: " << i << std::endl;
}
int main(int argc, const char *argv[]) {
ThreadManager mgr;
auto t = mgr.newThread(foo, 10);
t.detach();
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
return 0;
}我在LLVM编译器中使用Xcode 7.1,但在FreeBSD clang3.3上也失败了。
Xcode错误是:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/thread:337:5:错误:尝试使用已删除的函数__invoke(_VSTD::move(_VSTD::get<0>(__t))、_VSTD::move(_VSTD::get<_Indices>(__t)).);^ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/thread:347:5:注:在实例化函数模板专门化'std::__1::__thread_execute‘这里请求__thread_execute(*__p,_Index());^ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/thread:359:42:注:在实例化函数模板专门化'std::__1::__thread_proxy >‘这里请求的int __ec = pthread_create(&__t_,0,&__thread_proxy<_Gp>,__p.get());
发布于 2015-10-25 15:46:03
在您的示例中,我不确定是什么导致了“尝试使用已删除的函数”,我得到了与std::thread的绑定机制相关的其他错误。
thread_wrapper的模板参数的拼写方式似乎与std::thread的构造函数不太好--尤其是当它在内部使用简化的std::bind时。完美转发的函数类型和std::decayed函数指针的混合似乎使std::result_of感到不安。
我们可以通过自己在std::decay中应用newThread来实现它:
return std::thread( thread_wrapper<typename std::decay<F>::type,
typename std::decay<Args>::type...>,
std::forward<F>(f),
std::forward<Args>(args)... );老实说,...but,我不完全确定这是为什么。
或者,使用一些间接和更多的转发,我们可以避免拼写模板参数。我们只需要一个函子转发到thread_wrapper (或者C++14中的多态lambda ):
struct wrapper_helper {
template<class F, class... Args>
void operator()(F&& f, Args&&... args) const {
thread_wrapper(std::forward<F>(f), std::forward<Args>(args)...);
}
};并在newThread中使用
return std::thread(wrapper_helper{}, std::forward<F>(f), std::forward<Args>(args)...);下面是一个完整的示例,显示按值、引用和rvalue引用传递的参数,这些参数按预期工作:http://coliru.stacked-crooked.com/a/b75d5a264f583237
注意:对于std::unique_ptr这样的仅移动类型,您肯定希望在thread_wrapper中转发args...。
https://stackoverflow.com/questions/33327686
复制相似问题