【问题标题】:How to implement wrapper for lambda with capture? [duplicate]如何使用捕获实现 lambda 包装器? [复制]
【发布时间】:2021-04-12 21:39:46
【问题描述】:

std::function 可以用捕获列表包装 lambda,但 std::function 是如何实现的?我们不知道它是什么类型的,可以赋值给void*但是之后就不能调用lambda了

【问题讨论】:

  • 你看过 libstdc++ 和 libc++ 中的实现吗?
  • @StephenNewell 图书馆就是一团糟

标签: c++ c++11 lambda


【解决方案1】:

免责声明:这是不完整的,可能不正确,并且不遵循 std::function api 和约定(例如,它不可复制)。这只是一个示例,展示了如何实现 std::function 类似类型的类型擦除的一种方法,将其精简到最低限度以了解类型擦除技术。

为了存储任何类型并能够根据函数签名调用它,我们使用了多态性。

这是定义调用 API 的 Signature 的基本抽象类。 Signature 必须是函数类型:

template <class Signature> struct CallableBase;

template <class R, class... Args>
struct CallableBase<R(Args...)>
{
    virtual R call(Args... args) = 0;
};

接下来我们需要一个派生类来保存实际的可调用对象F 并可以调用它:

template <class F, class Signature> struct Callable;

template <class F, class R, class... Args>
struct Callable<F, R(Args...)> : CallableBase<R(Args...)>
{
    F f;

    Callable(F f) : f{f} {}

    R call(Args... args) override
    {
        return f(args...);
    }
};

在我们的Function 类中,我们持有一个CallableBase 类型的指针,指向Callable&lt;F&gt; 类型的对象,以启用多态性并获得所需的行为:

template <class Signature> struct Func;

template <class R, class... Args>
struct Func<R(Args...)>
{
    using Signature = R(Args...);

    std::unique_ptr<CallableBase<Signature>> callable_;

    template <class F>
    Func(F f) : callable_{std::make_unique<Callable<F, Signature>>(f)} {}

    R operator()(Args... args)
    {
        return callable_->call(args...);
    }
};

这让我们得到了一个基本类型被删除Function

auto test()
{
    int x = 10;

    Func<int(int, int)> f = [=] (int a, int b) { return a * x + b; };

    return f(2, 5); // 25
}

【讨论】:

    猜你喜欢
    • 2018-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-11
    • 2016-04-08
    • 2015-12-05
    相关资源
    最近更新 更多