我正在尝试创建std::function一个移动捕获lambda表达式.请注意,我可以创建一个移动捕获lambda表达式而不会出现问题; 只有当我尝试将其包装成一个std::function我得到错误时.
例如:
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);
Run Code Online (Sandbox Code Playgroud)
我会解释为什么我要写这样的东西.我写了一个UI库,类似于jQuery的或JavaFX的,允许用户通过传递给处理鼠标/键盘事件std::functions到方法有相似的名字on_mouse_down(),on_mouse_drag(),push_undo_action(),等.
显然,std::function我想要传入的理想情况下应该使用移动捕获lambda表达式,否则我需要求助于我在C++ 11作为标准时使用的丑陋的"release/acquire-in-lambda"习语:
std::function<void()> baz = …Run Code Online (Sandbox Code Playgroud) 这个答案解释了如何在C++ 14中移动捕获lambda中的变量.
但是,一旦你std::unique_ptr在lambda中移动捕获了一个不可复制的对象(例如a ),就无法复制lambda本身.
如果你可以移动 lambda,那就没问题,但是在尝试这样做时我遇到了编译错误:
using namespace std;
class HasCallback
{
public:
void setCallback(std::function<void(void)>&& f)
{
callback = move(f);
}
std::function<void(void)> callback;
};
int main()
{
auto uniq = make_unique<std::string>("Blah blah blah");
HasCallback hc;
hc.setCallback(
[uniq = move(uniq)](void)
{
std::cout << *uniq << std::endl;
});
hc.callback();
}
Run Code Online (Sandbox Code Playgroud)
这会产生以下错误g++(我试图只复制相关的行):
error: use of deleted function ‘main()::<lambda()>::<lambda>(const main()::<lambda()>&’
Run Code Online (Sandbox Code Playgroud)
......我想,我暗示我移动lambda的尝试失败了.
clang++ 给出了类似的错误.
我试着明确地move使用lambda(即使它是一个临时值),但这没有帮助.
编辑:下面的答案充分解决了上述代码产生的编译错误.对于另一种方法,简单地release将唯一的指针的目标值成std::shared_ptr,它可以被复制.(我不是写这个作为答案,因为这会假设这是一个XY问题,但是为什么unique_ptr不能在被转换为a的lambda中使用的根本原因std::function很重要.) …
我想创建一个状态机,它在自己的线程中处理提交的信号.我使用Visual Studio 2015,因此支持C++ 11和部分C++ 14.信号存储在容器中.每个信号表示为std :: function.我想从客户端等待,直到状态机处理提交的信号,因此它是一种同步信号.
我的问题是:我无法将std :: promise捕获到lambda中并将其添加到容器中.
#include <functional>
#include <future>
#include <list>
std::list<std::function<int()>> callbacks;
void addToCallbacks(std::function<int()>&& callback)
{
callbacks.push_back(std::move(callback));
}
int main()
{
std::promise<int> prom;
auto fut = prom.get_future();
// I have made the lambda mutable, so that the promise is not const, so that I can call the set_value
auto callback = [proms{ std::move(prom) }]() mutable { proms.set_value(5); return 5; };
// This does not compile
addToCallbacks(std::move(callback));
// This does not compile either, however this …Run Code Online (Sandbox Code Playgroud) 在将 lambda 转换为 的过程中是否复制了捕获的参数std::function?
我需要将捕获不可复制类型的 lambda 转换为std::function.
所以我将一个 lambdastd::function作为右值传递给,但发生了错误。
// Foo is non-copyable.
auto a = [f = Foo()]{ };
std::function<void()> b = std::move(a) // error, calls deleted Foo::Foo(const Foo&);
Run Code Online (Sandbox Code Playgroud) 我一直在尝试将 packaged_task 捕获到 lambda 中,但失败了。
\n我完全理解动作语义,也读过一些现代文学,我想我没有错过任何东西。我还阅读了 Josuttis 的移动语义书,以及关于广义 lambda 捕获的 ISO 主题以及ISO C++ 14 语言扩展
中的类似案例\n我有下一个代码:
#include <thread>\n#include <vector>\n#include <functional>\n#include <queue>\n#include <condition_variable>\n#include <mutex>\n#include <future>\n#include <type_traits>\n#include <iostream>\n\n// #include\'s for below code and other purposes\n\nint main() {\n auto f = []() { return 1; }; \n std::queue<std::function<void()>> q;\n std::packaged_task<int()> pack(f);\n q.emplace([p = std::move(pack)] () mutable { p(); });\n\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n\n这里我创建了简单的函数队列,保存一些“void()”和packaged_task,传递“int”返回类型的“f”。
\n然后我尝试将 packaged_task 移动到 lambda 中以便稍后在其他线程中使用它(我需要在其他线程中使用它,这将在稍后执行它,当“pack”将被销毁时,这就是为什么我不能引用它)
\n看起来一切都很好,但是当我用“g++ main.cpp -o main -std=c++14”(甚至使用c++17)编译它时, g++ 告诉我这个:
\n/usr/include/c++/9/bits/std_function.h:176:6: 错误:使用已删除的函数 \xe2\x80\x98main()::::(const main()::&)\xe2\x80 …
根据http://en.cppreference.com/w/cpp/utility/functional/function/function,初始化程序的类型,即F形式(5),应满足CopyConstructible的要求.我不太懂.为什么F只是MoveConstructible不行?
以下代码无法编译.因为pt有类型const std::packaged_task<void()>>而operator()不是const.
auto packagedTask = std::packaged_task<void()>>([]{});
auto future = packagedTask.get_future();
auto function = [pt = std::move(packagedTask)]{ (*pt)(); });
Run Code Online (Sandbox Code Playgroud)
这是解决方法:
auto packagedTask = std::make_shared<std::packaged_task<void()>>([]{});
auto future = packagedTask->get_future();
auto function = [pt = std::move(packagedTask)]{ (*pt)(); });
Run Code Online (Sandbox Code Playgroud)
为什么lambda对象中的局部变量是const?我想让第一个代码工作,而不需要管理工作量的开销.解决问题的最佳做法是什么?
我正在尝试使用auto作为返回的lambda函数的返回类型。这是一个最小的示例,它演示了我遇到的一个问题:
#include <iostream>
#include <memory>
auto
get_func()
{
auto i = std::make_unique<int>(2);
if (*i == 1) {
return [i=std::move(i)]() {
return *i;
};
}
return [](){ return 2; };
}
int
main(int argc, char* argv[])
{
auto func = get_func();
std::cout << "val: " << func() << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在我的Mac上,出现以下编译错误:
$ g++ -g -Wall -Werror -std=c++17 test.cc -o test
test.cc:13:5: error: 'auto' in return type deduced as '(lambda at test.cc:13:12)' here but deduced as '(lambda at test.cc:9:16)' in …Run Code Online (Sandbox Code Playgroud) 我有一个类,其中删除了复制赋值运算符和复制构造函数,只留下了移动赋值运算符和移动构造函数。例如:
struct Number {
public:
int *pNum;
Number &operator=(const Number &rhs) = delete;
Number(const Number &rhs) = delete;
Number &operator=(Number &&rhs) {
if (&rhs == this) {
return *this;
}
pNum = rhs.pNum;
rhs.pNum = nullptr;
return *this;
}
Number() = default;
Number(Number &&rhs) {
*this = std::move(rhs);
}
~Number() {
delete pNum;
}
};
Run Code Online (Sandbox Code Playgroud)
现在,我想使用std::move将这个类捕获到一个 lambda 中。例如:
int main() {
std::function<int(int)> add;
int a = 3;
{
Number n{};
n.pNum = new int;
*n.pNum = 5;
add …Run Code Online (Sandbox Code Playgroud)