std :: function和std :: packaged_task转换

yng*_*ccc 9 c++ clang c++11

我想移动std::packaged_taskstd::vectorstd::function<void()>,因为std::packaged_task已经void operator()( ArgTypes... args )过载,它应该是可转换到std::function<void()>,是吗?

这不能在MSVC和Clang上编译,MSVC抱怨无法将void转换为int,clang抱怨删除了复制构造函数std::packaged_task,不应该移动版本在std::vector::push_back这里调用?发生了什么,这是一个错误吗?

int main () 
{
    std::vector<std::function<void()>> vec;
    std::packaged_task<int()> task( [] { return 100; } );
    vec.push_back( std::move(task) );
}
Run Code Online (Sandbox Code Playgroud)

这是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.
Run Code Online (Sandbox Code Playgroud)

Jon*_*ely 13

它应该可转换为std::function<void()>,是吗?

function不需要.相关的构造函数要求其参数为CopyConstructible而packaged_task不是CopyConstructible,它只是MoveConstructible,因为它的复制构造函数和复制赋值运算符被删除.由于使用类型擦除来抽象包装的可调用对象的细节,因此这是一个令人遗憾的要求,function但是必须是function可复制的.

直到过程已经很晚了的C++ 0x草案没有要求拷贝构造,但它被添加到最终的C++标准的11 DR 1287所以这是我的错,对不起;-)较早启用概念草案已经要求CopyConstructible概念,但是当从草案中删除概念时就会丢失.