类型擦除通过基类虚函数统一接口,模板派生类保存具体可调用对象,包装器持基类指针实现值语义,支持任意可调用类型但隐藏具体类型,如简易std::function实现所示。

类型擦除(Type Erasure)是一种让不同类型共享统一接口的技术,常用于实现类似 std::function 的泛型函数包装器。它能隐藏具体类型信息,只暴露行为接口,从而实现运行时多态而无需继承体系。
基本思路:封装可调用对象
目标是实现一个通用的函数包装器,支持任意可调用类型(函数指针、lambda、仿函数等),但对外呈现统一类型。核心是把“具体类型”擦除,只保留“调用能力”。
我们通过以下组件实现:
基类接口:定义调用操作的虚函数 模板派生类:保存具体可调用对象 包装器类:持有基类指针,提供值语义
手动实现简易 std::function
下面是一个简化版的函数包装器,支持无参返回 int 的调用:
立即学习“C++免费学习笔记(深入)”;
#include #include class Function { struct CallableBase { virtual ~CallableBase() = default; virtual int call() = 0; virtual std::unique_ptr clone() const = 0; }; template struct CallableModel : CallableBase { F func; explicit CallableModel(F f) : func(std::move(f)) {} int call() override { return func(); } std::unique_ptr clone() const override { return std::make_unique(func); } }; std::unique_ptr callable;public: Function() = default; template Function(F f) : callable(std::make_unique<CallableModel>(std::move(f))) {} Function(const Function& other) : callable(other.callable ? other.callable->clone() : nullptr) {} Function& operator=(const Function& other) { if (this != &other) { callable = other.callable ? other.callable->clone() : nullptr; } return *this; } Function(Function&&) = default; Function& operator=(Function&&) = default; int operator()() const { if (!callable) throw std::bad_function_call(); return callable->call(); } explicit operator bool() const { return !!callable; }};
使用示例:
int foo() { return 42; }int main() { Function f1 = []{ return 100; }; Function f2 = foo; std::cout << f1() << "n"; // 输出 100 std::cout << f2() << "n"; // 输出 42 Function f3 = f1; std::cout << f3() << "n"; // 输出 100}
支持任意签名和参数
要支持不同函数签名,可将 Function 改为模板:
template class Function;template class Function { struct CallableBase { virtual ~CallableBase() = default; virtual R call(Args... args) = 0; virtual std::unique_ptr clone() const = 0; }; template struct CallableModel : CallableBase { F func; explicit CallableModel(F f) : func(std::move(f)) {} R call(Args... args) override { return func(std::forward(args)...); } std::unique_ptr clone() const override { return std::make_unique(func); } }; std::unique_ptr callable;public: Function() = default; template Function(F f) : callable(std::make_unique<CallableModel>(std::move(f))) {} Function(const Function& other) : callable(other.callable ? other.callable->clone() : nullptr) {} Function& operator=(const Function& other) { if (this != &other) { callable = other.callable ? other.callable->clone() : nullptr; } return *this; } Function(Function&&) = default; Function& operator=(Function&&) = default; R operator()(Args... args) const { if (!callable) throw std::bad_function_call(); return callable->call(std::forward(args)...); } explicit operator bool() const { return !!callable; }};
性能与优化考虑
上述实现每次调用都有虚函数开销。实际如 std::function 会结合小对象优化(Small Buffer Optimization),在栈上存储小型可调用对象,避免堆分配。
关键点:
类型擦除牺牲部分性能换取接口统一 避免频繁拷贝包装器,尤其含大闭包的 lambda 注意异常安全和资源管理(使用智能指针)
基本上就这些。不复杂但容易忽略细节,比如正确实现拷贝语义和所有权转移。
以上就是c++++怎么实现一个类型擦除(Type Erasure)的函数包装器_C++泛型编程与类型擦除技巧的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1484454.html
微信扫一扫
支付宝扫一扫