c++ 将 捕获 unique _ ptr 的 lambda 传递 给 另 一 个 函数

c9qzyr3d  于 2022-11-19  发布在  其他
关注(0)|答案(1)|浏览(161)

我想传递一个可变lambda,它捕获一个unique_ptr到另一个函数,如下面的代码片段所示。

#include <functional>
#include <memory>
#include <iostream>

struct Adder {
    Adder(int val1, std::unique_ptr<int> val2) : val1_(val1), val2_(std::move(val2)) {
    }

    int Add() {
        return val1_ + *val2_;
    }

    int val1_;
    std::unique_ptr<int> val2_;
};

void CallAdder(std::function<int ()> func) {
    std::cout << func() << "\n";
}

int main() {
    auto ptr = std::make_unique<int>(40);
    int byRef = 2;
    auto lam = [&, p = std::move(ptr)]() mutable
    {
        return Adder(byRef, std::move(p)).Add();
    };

    CallAdder(std::move(lam));
}

上面的代码给了我一个lambda的删除复制构造函数错误,如下所示。

$ clang++-14 -o lam lambda.cc
In file included from lambda.cc:2:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/functional:59:
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/std_function.h:161:10: error: call to implicitly-deleted copy constructor of '(lambda at lambda.cc:25:16)'
            new _Functor(*__source._M_access<const _Functor*>());
                ^        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/std_function.h:196:8: note: in instantiation of member function 'std::_Function_base::_Base_manager<(lambda at lambda.cc:25:16)>::_M_clone' requested here
              _M_clone(__dest, __source, _Local_storage());
              ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/std_function.h:283:13: note: in instantiation of member function 'std::_Function_base::_Base_manager<(lambda at lambda.cc:25:16)>::_M_manager' requested here
            _Base::_M_manager(__dest, __source, __op);
                   ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/std_function.h:611:33: note: in instantiation of member function 'std::_Function_handler<int (), (lambda at lambda.cc:25:16)>::_M_manager' requested here
            _M_manager = &_My_handler::_M_manager;
                                       ^
lambda.cc:30:15: note: in instantiation of function template specialization 'std::function<int ()>::function<(lambda at lambda.cc:25:16), void, void>' requested here
    CallAdder(std::move(lam));
              ^
lambda.cc:25:20: note: copy constructor of '' is implicitly deleted because field '' has a deleted copy constructor
    auto lam = [&, p = std::move(ptr)]() mutable
                   ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/unique_ptr.h:468:7: note: 'unique_ptr' has been explicitly marked deleted here
      unique_ptr(const unique_ptr&) = delete;
      ^

我也试着按照cannot pass deleted lambda function with move?传递lambda作为引用,但是我得到了一个类型错误,它抱怨它不能对CallAdder签名中的std::function进行lambda类型检查。我该如何修复这个错误?

vsaztqbk

vsaztqbk1#

您可以在函数参数上建立CallAdder模板。
Demo(https://godbolt.org/z/fb7rjYGx4)

#include <functional>
#include <iostream>
#include <memory>

struct Adder {
    Adder(int val1, std::unique_ptr<int> val2)
        : val1_(val1), val2_(std::move(val2)) {}

    int Add() { return val1_ + *val2_; }

    int val1_;
    std::unique_ptr<int> val2_;
};

template <typename F>
void CallAdder(F&& func) { std::cout << std::forward<F>(func)() << "\n"; }

int main() {
    auto ptr = std::make_unique<int>(40);
    int byRef = 2;
    auto lam = [&byRef, p = std::move(ptr)]() mutable {
        return Adder(byRef, std::move(p)).Add();
    };

    CallAdder(std::move(lam));
}

// Outputs: 42

或者只是:
Demo(https://godbolt.org/z/8d85r4xhM)

#include <functional>
#include <iostream>
#include <memory>

struct Adder {
    Adder(int val1, std::unique_ptr<int> val2)
        : val1_(val1), val2_(std::move(val2)) {}

    int Add() { return val1_ + *val2_; }

    int val1_;
    std::unique_ptr<int> val2_;
};

void CallAdder(std::function<int()> func) { std::cout << func() << "\n"; }

int main() {
    auto ptr = std::make_unique<int>(40);
    int byRef = 2;
    auto lam = [&]() {
        return Adder(byRef, std::move(ptr)).Add();
    };

    CallAdder(lam);
}

相关问题