Я пытаюсь создать std::function
из выражения лямбда-перемещения. Обратите внимание, что я могу без проблем создавать захватывающее лямбда-выражение; это только когда я пытаюсь обернуть его в 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);
Я объясню, почему я хочу написать что-то вроде этого. Я написал библиотеку UI, которая, подобно jQuery или JavaFX, позволяет пользователю обрабатывать события мыши/клавиатуры, передавая std::function
методам с именами типа on_mouse_down()
, on_mouse_drag()
, push_undo_action()
и т.д.
Очевидно, что std::function
, который я хочу передать, должен в идеале использовать выражение лямбда для перемещения, в противном случае мне нужно прибегнуть к уродливой идиоме "release/приобретать-в-лямбда", которую я использовал, когда С++ 11 был стандартным:
std::function<void()> baz = [q = pi.release()] {
std::unique_ptr<int> p{q};
*p = 5;
std::cout << *q << std::endl;
};
Обратите внимание, что вызов baz
дважды будет ошибкой в указанном выше коде. Однако в моем коде это закрытие гарантировано вызывается ровно один раз.
Кстати, в моем реальном коде я не передаю std::unique_ptr<int>
, а что-то более интересное.
Наконец, я использую Xcode6-Beta4, который использует следующую версию 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