How to create an std::function from a move-capturing lambda expression?(如何从捕获移动的 lambda 表达式创建 std::function?)
问题描述
我正在尝试从捕获移动的 lambda 表达式创建一个 std::function
.请注意,我可以毫无问题地创建一个移动捕获 lambda 表达式;只有当我尝试将它包装在 std::function
中时,我才会收到错误.
I'm trying to create an std::function
from a move-capturing lambda expression. Note that I can create a move-capturing lambda expression without problems; it's only when I try to wrap it in an std::function
that I get an error.
例如:
auto pi = std::make_unique<int>(0);
// no problems here!
auto foo = [q = std::move(pi)] {
*q = 5;
std::cout << *q << std::endl;
};
// All of the attempts below yield:
// "Call to implicitly-deleted copy constructor of '<lambda...."
std::function<void()> bar = foo;
std::function<void()> bar{foo};
std::function<void()> bar{std::move(foo)};
std::function<void()> bar = std::move(foo);
std::function<void()> bar{std::forward<std::function<void()>>(foo)};
std::function<void()> bar = std::forward<std::function<void()>>(foo);
我会解释为什么我想写这样的东西.我编写了一个类似于 jQuery 或 JavaFX 的 UI 库,它允许用户通过将 std::function
传递给名称类似于 on_mouse_down()<的方法来处理鼠标/键盘事件/code>、
on_mouse_drag()
、push_undo_action()
等
I'll explain why I want to write something like this. I've written a UI library which, similar to jQuery or JavaFX, allows the user to handle mouse/keyboard events by passing std::function
s to methods with names like on_mouse_down()
, on_mouse_drag()
, push_undo_action()
, etc.
显然,我想传入的 std::function
理想情况下应该使用移动捕获 lambda 表达式,否则我需要诉诸丑陋的release/acquire-in-lambda"习语我在 C++11 是标准时使用:
Obviously, the std::function
I want to pass in should ideally use a move-capturing lambda expression, otherwise I need to resort to the ugly "release/acquire-in-lambda" idiom I was using when C++11 was the standard:
std::function<void()> baz = [q = pi.release()] {
std::unique_ptr<int> p{q};
*p = 5;
std::cout << *q << std::endl;
};
请注意,在上述代码中两次调用 baz
将是错误的.但是,在我的代码中,这个闭包保证只被调用一次.
Note that calling baz
twice would be an error in the above code. However, in my code, this closure is guaranteed to be called exactly once.
顺便说一句,在我的真实代码中,我没有传递 std::unique_ptr
,而是一些更有趣的东西.
BTW, in my real code, I'm not passing an std::unique_ptr<int>
, but something more interesting.
最后,我使用 Xcode6-Beta4,它使用以下版本的 clang:
Finally, I'm using Xcode6-Beta4 which uses the following version of clang:
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.3.0
Thread model: posix
推荐答案
template
函数(F f);
模板
要求: F
应该是 CopyConstructible
.对于参数类型 ArgTypes
和返回类型 R
,f
应该是 Callable
.A 的拷贝构造函数和析构函数不应抛出异常.
Requires: F
shall be CopyConstructible
. f
shall be Callable
for argument types ArgTypes
and return type R
. The copy constructor and destructor of A shall not throw exceptions.
§20.9.11.2.1 [func.wrap.func.con]
§20.9.11.2.1 [func.wrap.func.con]
注意operator =
是根据这个构造函数和swap
定义的,所以同样的限制适用:
Note that operator =
is defined in terms of this constructor and swap
, so the same restrictions apply:
template
效果: function(std::forward
§20.9.11.2.1 [func.wrap.func.con]
§20.9.11.2.1 [func.wrap.func.con]
所以要回答你的问题:是的,可以从移动捕获的 lambda 构造一个 std::function
(因为这仅指定了 lambda 捕获的方式),但它是 不可能从仅移动类型构造std::function
(例如移动捕获的lambda,它移动捕获不是复制的东西可施工).
So to answer your question: Yes, it is possible to construct a std::function
from a move-capturing lambda (since this only specifies how the lambda captures), but it is not possible to construct a std::function
from a move-only type (e.g. a move-capturing lambda which move-captures something that is not copy constructible).
这篇关于如何从捕获移动的 lambda 表达式创建 std::function?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:如何从捕获移动的 lambda 表达式创建 std::function?


基础教程推荐
- 如何“在 Finder 中显示"或“在资源管理器中显 2021-01-01
- 如何在不破坏 vtbl 的情况下做相当于 memset(this, ...) 的操作? 2022-01-01
- 使用从字符串中提取的参数调用函数 2022-01-01
- 从 std::cin 读取密码 2021-01-01
- 为 C/C++ 中的项目的 makefile 生成依赖项 2022-01-01
- 在 C++ 中循环遍历所有 Lua 全局变量 2021-01-01
- 管理共享内存应该分配多少内存?(助推) 2022-12-07
- 如何使图像调整大小以在 Qt 中缩放? 2021-01-01
- Windows Media Foundation 录制音频 2021-01-01
- 为什么语句不能出现在命名空间范围内? 2021-01-01