C++ std::函数和std::打包的任务转换
我试图将C++ std::函数和std::打包的任务转换,c++,c++11,clang,C++,C++11,Clang,我试图将std::packaged_任务移动到std::function的std::vector,因为std::packaged_任务具有void操作符()(ArgTypes…args)重载,它应该可以转换为std::function,是吗 这不能在MSVC和Clang上编译,MSVC抱怨无法将void转换为int,Clang抱怨为std::packaged_task删除了复制构造函数,不应该在这里调用std::vector::push_的版本?怎么回事,这是个虫子吗 int main ()
std::packaged_任务
移动到std::function
的std::vector
,因为std::packaged_任务
具有void操作符()(ArgTypes…args)
重载,它应该可以转换为std::function
,是吗
这不能在MSVC和Clang上编译,MSVC抱怨无法将void转换为int,Clang抱怨为std::packaged_task
删除了复制构造函数,不应该在这里调用std::vector::push_的版本?怎么回事,这是个虫子吗
int main ()
{
std::vector<std::function<void()>> vec;
std::packaged_task<int()> task( [] { return 100; } );
vec.push_back( std::move(task) );
}
int main()
{
std::vec;
std::打包的_任务任务([]{return 100;});
向量推回(标准::移动(任务));
}
下面是关于clang的神秘模板错误消息
In file included from main.cpp:1:
In file included from /usr/bin/../lib/c++/v1/iostream:38:
In file included from /usr/bin/../lib/c++/v1/ios:216:
In file included from /usr/bin/../lib/c++/v1/__locale:15:
In file included from /usr/bin/../lib/c++/v1/string:434:
In file included from /usr/bin/../lib/c++/v1/algorithm:594:
/usr/bin/../lib/c++/v1/memory:2236:15: error: call to deleted constructor of
'std::__1::packaged_task<int ()>'
__first_(_VSTD::forward<_Args1>(get<_I1>(__first_args))...)
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib/c++/v1/memory:2414:15: note: in instantiation of function
template specialization
'std::__1::__libcpp_compressed_pair_imp<std::__1::packaged_task<int ()>,
std::__1::allocator<std::__1::packaged_task<int ()> >,
2>::__libcpp_compressed_pair_imp<const std::__1::packaged_task<int ()> &,
const std::__1::allocator<std::__1::packaged_task<int ()> > &, 0, 0>'
requested here
: base(__pc, _VSTD::move(__first_args), _VSTD::move(__second_args),
^
/usr/bin/../lib/c++/v1/functional:996:11: note: in instantiation of function
template specialization
'std::__1::__compressed_pair<std::__1::packaged_task<int ()>,
std::__1::allocator<std::__1::packaged_task<int ()> >
>::__compressed_pair<const std::__1::packaged_task<int ()> &, const
std::__1::allocator<std::__1::packaged_task<int ()> > &>' requested here
: __f_(piecewise_construct, _VSTD::forward_as_tuple(__f),
^
/usr/bin/../lib/c++/v1/functional:1035:17: note: in instantiation of member
function 'std::__1::__function::__func<std::__1::packaged_task<int ()>,
std::__1::allocator<std::__1::packaged_task<int ()> >, void ()>::__func'
requested here
::new (__p) __func(__f_.first(), __f_.second());
^
/usr/bin/../lib/c++/v1/functional:1277:26: note: in instantiation of member
function 'std::__1::__function::__func<std::__1::packaged_task<int ()>,
std::__1::allocator<std::__1::packaged_task<int ()> >, void ()>::__clone'
requested here
::new (__f_) _FF(_VSTD::move(__f));
^
/usr/bin/../lib/c++/v1/memory:1681:31: note: in instantiation of function
template specialization 'std::__1::function<void
()>::function<std::__1::packaged_task<int ()> >' requested here
::new((void*)__p) _Up(_VSTD::forward<_Args>(__args)...);
^
/usr/bin/../lib/c++/v1/memory:1608:18: note: in instantiation of function
template specialization 'std::__1::allocator<std::__1::function<void ()>
>::construct<std::__1::function<void ()>, std::__1::packaged_task<int ()>
>' requested here
{__a.construct(__p, _VSTD::forward<_Args>(__args)...);}
^
/usr/bin/../lib/c++/v1/memory:1492:14: note: in instantiation of function
template specialization
'std::__1::allocator_traits<std::__1::allocator<std::__1::function<void
()> > >::__construct<std::__1::function<void ()>,
std::__1::packaged_task<int ()> >' requested here
{__construct(__has_construct<allocator_type, pointer, _Args...>(),
^
/usr/bin/../lib/c++/v1/vector:1519:25: note: in instantiation of function
template specialization
'std::__1::allocator_traits<std::__1::allocator<std::__1::function<void
()> > >::construct<std::__1::function<void ()>,
std::__1::packaged_task<int ()> >' requested here
__alloc_traits::construct(this->__alloc(),
^
main.cpp:19:6: note: in instantiation of function template specialization
'std::__1::vector<std::__1::function<void ()>,
std::__1::allocator<std::__1::function<void ()> >
>::emplace_back<std::__1::packaged_task<int ()> >' requested here
vec.emplace_back( std::move(task) );
^
/usr/bin/../lib/c++/v1/future:1956:5: note: function has been explicitly marked
deleted here
packaged_task(const packaged_task&) = delete;
^
2 errors generated.
在main.cpp:1中包含的文件中:
在/usr/bin/./lib/c++/v1/iostream:38中包含的文件中:
在/usr/bin/./lib/c++/v1/ios:216中包含的文件中:
在/usr/bin/./lib/c++/v1/_语言环境15中包含的文件中:
在/usr/bin/./lib/c++/v1/string:434中包含的文件中:
在/usr/bin/./lib/c++/v1/算法中包含的文件中:594:
/usr/bin/。/lib/c++/v1/内存:2236:15:错误:调用的已删除构造函数
'std::_1::打包的_任务'
__第一个参数(_-VSTD::forward(get(u-first-args))…)
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/。/lib/c++/v1/memory:2414:15:注意:在函数的实例化中
模板特化
'std::uu 1::uu libcpp\u compressed\u pair\u imp::u libcpp\u compressed\u pair\u imp'
在此请求
:base(uu pc,_VSTD::move(u first_args),_VSTD::move(u second_args),
^
/usr/bin/。/lib/c++/v1/functional:996:11:注意:在函数的实例化中
模板特化
“std::uu 1::u compressed_pair::u compressed_pair”已在此处请求
:uu f_u(分段构造,_-VSTD::前向作为元组(u f),
^
/usr/bin/。/lib/c++/v1/functional:1035:17:注意:在成员的实例化中
函数'std::u 1::u函数::u func::u func'
在此请求
::新建(u p)u func(u f_u.first(),u f_u.second());
^
/usr/bin/。/lib/c++/v1/functional:1277:26:注意:在成员的实例化中
函数'std::uu 1::u函数::u函数::u克隆'
在此请求
::新建(u f_u)FF(_VSTD::move(u f));
^
/usr/bin/。/lib/c++/v1/memory:1681:31:注意:在函数的实例化中
此处请求的模板专门化“std::\uu 1::function::function”
::新建((void*)\u p)\u向上(\u VSTD::forward(\u args)…);
^
/usr/bin/。/lib/c++/v1/memory:1608:18:注意:在函数的实例化中
此处请求了模板专门化“std::\uu 1::分配器::构造”
{{构造({p,{VSTD::forward({args)…);}
^
/usr/bin/。/lib/c++/v1/memory:1492:14:注意:在函数的实例化中
模板特化
此处请求了“std::_1::分配器特征::_构造”
{{uuuu构造({uu有\u构造(),
^
/usr/bin/。/lib/c++/v1/vector:1519:25:注意:在函数的实例化中
模板特化
此处请求了“std::_1::分配器_traits::construct”
__alloc_traits::construct(this->alloc(),
^
main.cpp:19:6:注意:在函数模板专门化的实例化中
此处请求“std::_1::vector::emplace_back”
后置向量(标准::移动(任务));
^
/usr/bin/。/lib/c++/v1/future:1956:5:注意:函数已显式标记
此处删除
打包任务(const packaged_task&)=删除;
^
产生2个错误。
它应该可以转换为std::function
,是吗
否。函数
的相关构造函数要求其参数可复制,而打包的_任务
不可复制,它仅可移动,因为其复制构造函数和复制赋值运算符被删除。这是函数
的不幸要求,但对于乐趣来说是必要的Action
是可复制的,因为使用类型擦除来提取包装的可调用对象的详细信息
直到过程的后期,C++0x草案才要求可复制,但它是由最终的C++11标准添加的,所以这是我的错,对不起;-)早期支持概念的草案需要CopyConstructible
概念,但当概念从草案中删除时,这一概念就消失了。我今天遇到了这个问题。在异步服务中实现同步调用时,显然要做的事情是尝试将打包的任务存储在处理程序函数中,以便当异步处理程序完成时,调用方的未来可以准备就绪
不幸的是,c++11(和14)不允许这样做。跟踪它花费了我将近一天的开发时间,这个过程让我找到了这个答案
我找到了一个解决方案——用std::packaged_任务的专业化来替代std::function
感谢yngum和Jonathan发布问题和答案
代码:
//通用模板表单
模板
结构通用调用;
//部分专业化,涵盖大多数案例
模板
结构通用调用{
模板
通用呼叫(可呼叫和可呼叫)
:_impl{std::make_shared(std::forward(callable))}
{}
R运算符()(Args&&…Args)常量{
return _impl->call(std::forward(args)…);
}
私人:
结构概念{
虚拟R调用(Args&&…Args)=0;
virtual~concept()=默认值;
};
模板
结构模型:概念{
模型(可调用&可调用)
:_可调用(标准::移动(可调用))
{}
R调用(Args&&…Args)覆盖{
返回_可调用(std::forward(args)…);
}
可调用的,可调用的;
};
std::共享的ptr实现;
};
//特殊路径
// general template form
template<class Callable>
struct universal_call;
// partial specialisation to cover most cases
template<class R, class...Args>
struct universal_call<R(Args...)> {
template<class Callable>
universal_call(Callable&& callable)
: _impl { std::make_shared<model<Callable>>(std::forward<Callable>(callable)) }
{}
R operator()(Args&&...args) const {
return _impl->call(std::forward<Args>(args)...);
}
private:
struct concept {
virtual R call(Args&&...args) = 0;
virtual ~concept() = default;
};
template<class Callable>
struct model : concept {
model(Callable&& callable)
: _callable(std::move(callable))
{}
R call(Args&&...args) override {
return _callable(std::forward<Args>(args)...);
}
Callable _callable;
};
std::shared_ptr<concept> _impl;
};
// pathalogical specialisation for std::packaged_task -
// erases the return type from the signature
template<class R, class...Args>
struct universal_call<std::packaged_task<R(Args...)>>
: universal_call<void(Args...)>
{
using universal_call<void(Args...)>::universal_call;
};
// (possibly) helpful function
template<class F>
universal_call<F> make_universal_call(F&& f)
{
return universal_call<F>(std::forward<F>(f));
}
std::vector<std::function<void()>> vec;
using task_t = std::packaged_task<int()>;
task_t task([] { return 100; });
vec.emplace_back( [t = std::make_shared<task_t>(std::move(task))]() {
(*t)();
});