Этот ответ объясняет, как перемещать-захватывать переменную в лямбда в С++ 14.
Но как только вы перенесли захваченный объект (например, std::unique_ptr
), который не скопирован в лямбда, вы не можете скопировать сам лямбда.
Это было бы хорошо, если бы вы могли перемещать лямбда, но при попытке сделать это я получаю ошибку компиляции:
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();
}
Это вызывает следующую ошибку с g++
(я попытался скопировать только соответствующую строку):
error: use of deleted function ‘main()::<lambda()>::<lambda>(const main()::<lambda()>&’
... подразумевая, я думаю, что моя попытка переместить лямбда не удалась.
clang++
дает аналогичную ошибку.
Я пробовал явно move
включить лямбда (хотя это временное значение), но это не помогло.
EDIT: В нижеприведенных ответах адекватно рассматриваются ошибки компиляции, создаваемые приведенным выше кодом. Для альтернативного подхода просто release
уникальное целевое значение указателя в std::shared_ptr
, которое можно скопировать. (Я не пишу это как ответ, потому что это предполагает, что это проблема XY, но основная причина, по которой unique_ptr
не может использоваться в лямбда, которая преобразуется в std::function
, важна для понимания.)
РЕДАКТИРОВАТЬ 2: Как ни странно, я просто понял, что auto_ptr
будет делать правильные вещи здесь (!), насколько я могу судить. Он действует, по существу, как unique_ptr
, но позволяет создавать копии вместо конструкции перемещения.