如何解决如何使用捕获实现 lambda 的包装器?
std::function
可以用捕获列表包装 lambda,但是 std::function
是如何实现的?我们不知道它的类型是什么,它可以分配给 void*
但这样就不可能调用 lambda
解决方法
免责声明:这是不完整的,可能不正确,并且不遵循 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<F>
的对象以启用多态并获得所需的行为:
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
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。