快速上手 Microsoft Proxy 库
2025-05-25 20:11:24
介绍
最近了解到了一个微软开源的 C++ 库Proxy
,并称其为下一代多态库,旨在解决 C++ 传统虚函数和继承带来的问题。
GitHub:https://github.com/microsoft/proxy
简单点说,这个库实现了类似 go 语言中的 interface。直接看一个例子就懂了,传统C++风格的多态:
1 | struct animal |
用了Proxy
后的样子:
1 |
|
区别很明显:dog
和cat
没有祖先类,也没有虚函数。只需要满足Facade
定义即可,成功干掉了虚函数。
构造方法
空接口
1 | pro::proxy<AnimalFacade> empty_facade; |
构造新实例
1 | pro::proxy<AnimalFacade> p1 = pro::make_proxy<AnimalFacade, dog>(); |
这三种构造方式的主要区别在于内存分配方式和生命周期管理:
pro::make_proxy
- 堆分配:在堆上创建
dog
对象 - 独占所有权:类似
std::unique_ptr
- 移动语义:只能移动,不能拷贝(除非指定
support_copy
)
pro::make_proxy_inplace
- 栈内分配:在
proxy
对象内部直接存储dog
- 无堆分配:性能更好,避免动态内存分配
- 大小限制:对象必须足够小以适应
proxy
的内部存储
pro::make_proxy_shared
- 共享所有权:类似
std::shared_ptr
- 引用计数:多个
proxy
可以共享同一个对象 - 自动销毁:当最后一个引用被销毁时,对象才被销毁
简短示例说明
1 | void demonstrate_differences() { |
选择建议:
- 性能优先且对象较小 →
make_proxy_inplace
- 需要共享 →
make_proxy_shared
- 一般情况 →
make_proxy
拷贝 support_copy
默认情况下是禁止 proxy 之间拷贝的
1 | auto p1 = pro::make_proxy<AnimalFacade, cat>(); |
除非在facade定义时显示设置允许拷贝
1 | struct AnimalFacade : pro::facade_builder |
support_copy
支持四个不同的 constraint_level
选项,它们定义了对象拷贝能力的不同约束级别:
1. constraint_level::none
- 含义:不支持拷贝
- 特点:
- 禁止拷贝操作
- 这是默认级别(如果不指定
support_copy
) - 适用于只移动(move-only)的类型
2. constraint_level::nontrivial
- 含义:支持非平凡拷贝
- 特点:
- 要求类型具有拷贝构造函数(
std::is_copy_constructible_v<T>
) - 允许有用户定义的拷贝构造函数
- 拷贝操作可能抛出异常
- 适用于大多数自定义类型
- 要求类型具有拷贝构造函数(
3. constraint_level::nothrow
- 含义:支持无异常拷贝
- 特点:
- 要求类型具有无异常拷贝构造函数(
std::is_nothrow_copy_constructible_v<T>
) - 拷贝操作保证不抛出异常
- 提供更强的异常安全保证
- 要求类型具有无异常拷贝构造函数(
4. constraint_level::trivial
- 含义:支持平凡拷贝
- 特点:
- 要求类型具有平凡拷贝构造函数和平凡析构函数
std::is_trivially_copy_constructible_v<T>
和std::is_trivially_destructible_v<T>
- 最高效的拷贝方式,通常可以使用
memcpy
- 适用于 POD 类型和简单结构
组合接口
1 | struct ReadFacade : pro::facade_builder |
默认情况下,接口无法向上转换
1 | auto p1 = pro::make_proxy<FileFacade, dog>(); |
需要显示指定add_facade
第2个参数为true
1 | struct FileFacade : pro::facade_builder |
要注意,转换时的拷贝行为
1. make_proxy
- 会发生拷贝
1 | auto p1 = pro::make_proxy<FileFacade, dog>(); // 堆分配,独占所有权 |
2. make_proxy_inplace
- 会发生拷贝
1 | auto p1 = pro::make_proxy_inplace<FileFacade, dog>(); // 栈内分配 |
3. make_proxy_shared
- 不会拷贝
1 | auto p1 = pro::make_proxy_shared<FileFacade, dog>(); // 共享所有权 |
总结
make_proxy
:堆上分配,类似std::unique_ptr
,独占所有权,默认只许移动。但可以设置support_copy
允许拷贝。make_proxy_inplace
:栈上分配,类似std::unique_ptr
,独占所有权,默认只许移动。可以显示设置support_copy
允许拷贝。make_proxy_shared
:堆上分配,类似std::shared_ptr
,共享所有权,不发生拷贝,只增加引用计数。