为什么我不能将元素移动到不可复制的向量中?
Why can't I move an element into vector of non-copyables?
编译器告诉我我正在尝试访问已删除的函数(即lambda表达式的复制构造函数(。但是我看不到哪里。
std::vector<std::function<void()>> tasks;
std::packaged_task<int()> task{ [] { return 1; } };
tasks.emplace_back(
[ t = std::move(task) ] () mutable { t(); });
(代码也在这里(
(我正在尝试找出为什么他们在https://www.slideshare.net/globallogicukraine/c11-multithreading-futures中使用shared_ptr<task>
(。
在GCC和MSVC上,我会遇到相同的错误 - 我担心自己做错了什么...
error: use of deleted function
'main()::<lambda()>::<lambda>(const main()::<lambda()>&)'
为什么我不能将此std::function
放在向量上?
来自cppreference:
f必须满足可呼叫和复制构造的要求
其中F
是用于构建std::function
的功能类型。但是,std::packaged_task
不能复制构造。因此,在捕获列表中, t
不是复制构造的,并且是lambda的非静态成员,使删除了lambda的隐式复制构造函数。
简短答案:lambdas和 std::packaged_task
不是 std::function
s。
长答案,您不能将std::packaged_task
移至std::function
这是我提供的解决方案:
std::vector<std::packaged_task<int()>> tasks;
std::packaged_task<int()> task{ [] () mutable { return 1; } };
tasks.emplace_back( std::move(task) );
如果您实际上需要一个std ::功能,而不仅仅是任何可召唤的功能,则必须将lambda绑定到std::function
std::function
的构造函数要求传递的函数对象为 CopyConstructible
,但 std::packaged_task<F>
不是(对于任何F
(。std::function
执行类型擦除,其中动态类型在静态类型中不可见。考虑例如:
int invoke(std::function<int()> f) { return f(); }
int main()
{
std::packaged_task<int()> p{/*etc*/};
auto l = [] { return 5; };
std::function<int()> f( /* either p or l */ );
std::cout << invoke(f) << 'n';
}
呼叫invoke
需要复制f
(按值通过(。但是,如果f
是由l
制成的,则可以复制,但如果它是由p
制成的,则不能复制,这与f
的静态类型无关。基本上有三种解决此问题的方法:
- 禁止在编译时复制
std::function
。 - 允许在编译时复制
std::function
,但是如果包含的类型不可复制,请在运行时错误。 - 允许在编译时复制
std::function
,并需要您放入其复制的任何功能对象。
方法#1对如何存储,通过和共享函数的方式非常限制,并且基本上禁止常见用例,而有利于不常见的情况使用不可拷贝的函数对象。
方法#2是有问题的,因为需要教育用户在某些情况下复制std::function
可能会失败,并且在编写代码时会非常勤奋。同样,如果设计需要共享功能,则可能需要将其包裹在std::shared_ptr
中。而且,如果需要复制并且可能是有状态的,那就变得更糟了。
无论您如何查看方法#3,都是标准化的方法。但是鉴于上述问题,也很容易辩护。
实际上,我编写了一个unique_function
类模板,该模板使用方法1用于我当前的项目不需要。
- 简单可复制与可简单复制
- reinterpret_cast,只读访问,简单的可复制类型,会出什么问题?
- 对于参加可复制和可移动类的访问者来说,应该有多少过载?
- 可变参数宏:无法通过"..."传递非平凡可复制类型的对象
- 为什么 std::atomic<std::string> 会给出微不足道的可复制错误?
- 我可以隐式地创建一个琐碎的可复制类型吗
- 是std::memcpy在不同的可复制类型之间的未定义行为
- 为什么一对常量是微不足道的可复制的,而对不是?
- 在一个微不足道的可复制结构中,移动语义应该实现吗?
- 防止作用域枚举可复制/可移动
- C :对象上的可复制视图
- 防御性地应用 std::move 到平凡可复制的类型是否不可取
- 为什么 std::function 本身是可复制构造的类型?
- C++不可复制的 lambda 的行为是可复制的
- 错误:无法通过'...'传递非平凡可复制类型的对象'class boost::filesystem::path'
- 不能让类是微不足道的可复制的。我做错了什么?
- 使用临时存储区复制普通的可复制类型:允许吗
- 使用realloc可以安全地重新分配琐碎的可复制对象的存储吗
- 在不使用元素复制赋值运算符的情况下复制向量 - 可移植性
- 为什么向量中的元素需要是可复制的