首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Lambda在转让所有权时按价值捕获

Lambda在转让所有权时按价值捕获
EN

Stack Overflow用户
提问于 2021-05-23 16:31:24
回答 1查看 207关注 0票数 0

我有一个RAII样式类,它管理所有权某些资源。因此,复制构造函数和赋值操作符被显式删除,只存在移动变体,它们移动资源并使源无效(引用)。到目前为止,它工作得很好,但是现在我想将这类对象移到一个std::function中,它在其他地方被处理,这样这个对象就成为了所有权载体,并最终释放了这个对象。幸运的是,C++14允许在捕获值的同时使用移动赋值,因此看起来就像要走的路。类似于:

代码语言:javascript
复制
std::function<void()> act = [temp = move(resCarrier), description]() mutable {
    try {
// hopefully exception-safe
        auto c = make_unique<DataProcessor>(move(temp), description);
        c->doStuff();
    }  catch (...) {}
};
scheduler->RunLater(move(act));

但不是那么容易。它应该可以工作,但它不能。得到混乱的模板错误,最终以这个结束(稍微简略地表示清楚)。

代码语言:javascript
复制
/usr/include/c++/10/bits/std_function.h:161:6: error: use of deleted function ‘<WHOLE SIGNATURE OF CURRENT FUNCTION>::<lambda()>&)’
...
note: ‘<WHOLE SIGNATURE OF CURRENT FUNCTION>::<lambda()>&)’ is implicitly deleted because the default definition would be ill-formed:
   99 |   std::function<void()> act = [temp = move(resCarrier), description]() mutable
      |                                                                    ^
...
error: use of deleted function ‘TResCarrier::TResCarrier(const TResCarrier&)’

因此,编译器似乎基本上忽略了move语义,坚持使用复制构造函数,同时捕获lambda声明中的变量。到目前为止,我无法说服它以不同的方式处理它。到目前为止,“最好”的想法是围绕所携带的对象创建另一个级别的重定向,以便可以通过值复制和捕获它(就像围绕资源的shared_ptr )。但这将是运行时开销,没有很好的理由。

我是忽略了什么,还是在std::函数后面隐藏了类型擦除的讨厌限制,还是lambda到函数映射的限制?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-05-23 17:09:26

lambda不是std::function

你是对的,c++14允许将某物移动到λ中,甚至在之后移动所述的lambda。

另一方面,std::function需要可调用的副本、可构造的副本和可分配的复制。

来自优先选择

类模板std::function是一个通用的多态函数包装器。函数实例可以存储、复制和调用任何CopyConstructible可调用的目标函数、lambda表达式、绑定表达式或其他函数对象,以及指向成员函数和数据成员指针的指针。存储的可调用对象称为std::function的目标。如果std::函数不包含目标,则称为空。调用空std::function的目标将导致抛出std::bad_function_call异常。功能满足CopyConstructible和CopyAssignable的要求。

一些可能的解决办法可以是:

  • 创建您自己的函数包装器(或使用一个库),它支持只移动的可调用项。
  • std::unique_pre包在一个std::shared_ptr中并捕获它。

第一种选择似乎要健壮得多,但仅仅是为了展示快速肮脏工作的想法。

代码语言:javascript
复制
#include <memory>
#include <functional>

int main() {
    auto moveonly = std::make_unique<int>(5);
    auto wrapped = std::make_shared<std::unique_ptr<int>>(std::move(moveonly));

    auto lam = [wrapped]() {
        return *(*wrapped);
    };

    std::function<int()> f = lam;
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67662035

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档