You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决捕获std::unique_ptr的Lambda无法移动到std::function的问题?

问题原因

std::function的底层实现要求它存储的可调用对象必须是可拷贝构造的。你的lambda因为捕获了std::unique_ptr(本身是不可拷贝的移动-only类型),导致整个lambda也变成了不可拷贝类型,所以直接赋值给std::function会触发target must be copy-constructible错误。

解决方案

方案1:C++23直接用std::move_only_function

C++23新增了std::move_only_function,专门用来存储不可拷贝的可调用对象,完美适配你的场景:

#include <functional>
#include <memory>

auto my_ptr = std::make_unique<int>(3);
auto my_lambda = [my_ptr = std::move(my_ptr)]() mutable {
    // 这里写你的逻辑
};
std::move_only_function<void()> func = std::move(my_lambda);

// 结构体中可以直接声明
struct MyStruct {
    std::move_only_function<void()> func;
};

方案2:兼容C++11/14/17的包装类

如果你的项目还不能用C++23,可以自己写一个轻量的包装类,把不可拷贝的lambda用std::unique_ptr持有,再适配成std::function接受的可调用类型:

#include <functional>
#include <memory>
#include <type_traits>

// 包装不可拷贝的可调用对象
struct MoveOnlyWrapper {
    // 用unique_ptr存储对象,自定义删除器
    std::unique_ptr<void, void(*)(void*)> storage;
    // 重载调用运算符
    void operator()() const {
        using Callable = void(*)();
        (*reinterpret_cast<Callable>(storage.get()))();
    }

    // 模板构造函数,接受任意移动-only的可调用对象
    template<typename F>
    MoveOnlyWrapper(F&& f) : storage(
        new std::decay_t<F>(std::forward<F>(f)),
        [](void* ptr) {
            delete static_cast<std::decay_t<F>*>(ptr);
        }
    ) {}
};

// 使用示例
auto my_ptr = std::make_unique<int>(3);
auto my_lambda = [my_ptr = std::move(my_ptr)]() mutable {
    // 这里写你的逻辑
};
std::function<void()> func = MoveOnlyWrapper(std::move(my_lambda));

// 结构体中声明
struct MyStruct {
    std::function<void()> func;
};

这个包装类的核心是把lambda的实例放到堆上,用unique_ptr管理,然后通过类型擦除让std::function能识别它的调用接口。

内容的提问来源于stack exchange,提问作者UdiM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 15:52:35