6,675
社区成员
发帖
与我相关
我的任务
分享Proxy 4 版本已正式发布!经过多年的创新,且自 2022 年起便在 Windows 操作系统代码库中持续投入使用,Proxy 已从一项大胆的实验,成熟为一款面向运行时多态性的生产级现代 C++ 库。Proxy 背后的理论具有原创性,其设计也已在大规模场景中得到验证。我们非常高兴能邀请广大 C++ 社区与我们一同塑造多态性的未来。你的想法与贡献,比以往任何时候都更受欢迎!
特别感谢 @SidneyCogdill 做出的杰出贡献,尤其是为 Proxy 带来了对 C++20 模块的支持,并推动了主版本兼容性相关工作。他的付出让这个库变得更易于使用,也更具前瞻性。
Proxy 是一个仅头文件、跨平台的 C++20 库,它让你能够编写多态代码,却无需承受继承带来的麻烦,也不必受传统虚函数的限制。借助 Proxy,你可以:
如果你刚接触 Proxy,不妨查看我们的 GitHub 代码仓库以及之前的公告:宣布推出支持动态多态的 Proxy 3 库和分析“Proxy”库的性能。
我们推出了一个全新的文档网站,基于 MkDocs 构建,助你找到关于 Proxy 的所有所需信息。新网站优化了导航布局,整合了常见问题解答,并为所有功能和 API 设计了清晰的结构。浏览文档,开启你的使用之旅吧!

现在你可以直接在浏览器中通过Compiler Explorer来试用 Proxy 了!无需任何安装,即可编写、运行并查看 Proxy 代码。只需在 Compiler Explorer 中点击“库”并搜索“proxy”,或者使用我们示例中的共享链接即可开始体验。这是了解 Proxy 实际应用并与他人分享你的发现的绝佳方式。

我们来看看为你的类型添加格式支持有多简单(在 Compiler Explorer 中运行):
#include <format>
#include <proxy/proxy.h>
struct Formattable : pro::facade_builder
::add_skill<pro::skills::format>
::build {};
int main() {
pro::proxy<Formattable> p = pro::make_proxy<Formattable>(123);
std::cout << std::format("{}\n", *p); // Prints "123"
}
技能是可复用的构建模块,只需一行代码,你就能为你的门面添加强大的功能:
skills::format 和 skills::wformat:为你的代理启用标准 C++ 格式化功能。这在虚函数或早期版本的 Proxy 中是无法实现的。skills::fmt_format 和 skills::fmt_wformat:为你的代理完整引入 {fmt} 库支持,让你无需编写冗余代码即可使用高级格式化功能。skills::rtti:为你的代理添加运行时类型信息和安全类型转换。skills::as_view 和 skills::as_weak:支持无缝转换为非拥有式或弱代理,让代码更安全、更具表达力。skills::slim:将你的代理限制为指针大小的存储,以实现最高效率。技能易于组合和扩展。你还可以编写内部的、特定领域的技能来捕获各类模式(日志记录、指标挂钩、验证、检测),这样团队就能复用一个经过充分审核的定义,而不必重复制定约定。这能提升一致性和长期可维护性。更多信息请参阅技能文档。
Proxy 4 为非拥有式引用和弱引用提供了便捷的别名:proxy_view 和 weak_proxy。这些功能基于核心的 proxy 概念构建,让你能更轻松地在代码中表达借用和弱所有权模式。例如,你可以使用 proxy_view 安全地借用对象而不获取其所有权,或使用 weak_proxy 创建一个可在需要时锁定的弱引用。有关详细信息,请参阅 proxy_view 文档和 weak_proxy 文档。
借助全新的 make_proxy_shared 和 allocate_proxy_shared 应用程序编程接口(API),你可以高效地创建共享代理和弱代理,无需承担 std::shared_ptr 带来的额外开销。这些应用程序编程接口(API)采用紧凑的内部指针类型,确保了高性能与低内存占用。如需了解更多信息,可查看 make_proxy_shared 文档和 allocate_proxy_shared 文档。
weak_dispatch 允许你为缺失的约定定义回退行为,从而让你的代码能够妥善处理不完整的类型。explicit_conversion_dispatch、implicit_conversion_dispatch)现在更易于使用,并且能提供更清晰的错误信息。proxiable_target和inplace_proxiable_target概念明确了哪些目标类型可与特定外观配合使用,助你避免意外情况并编写出更安全的代码。Proxy 4 引入了 facade_aware_overload_t,它允许你定义递归约定,这些约定可引用外观本身,且无需强制提前实例化。这对于返回相同外观的新 proxy对象的运算符链式模式(如算术运算或字符串拼接)特别有用。示例:
#include <format>
#include <iostream>
#include <proxy/proxy.h>
template <class F>
using BinaryOverload =
pro::proxy<F>(const pro::proxy_indirect_accessor<F>& rhs) const;
template <class T, pro::facade F>
pro::proxy<F> operator+(const T& value,
const pro::proxy_indirect_accessor<F>& rhs)
requires(!std::is_same_v<T, pro::proxy_indirect_accessor<F>>)
{
return pro::make_proxy<F, T>(value + proxy_cast<const T&>(rhs));
}
struct Addable
: pro::facade_builder // Compose capabilities
::add_skill<pro::skills::rtti> // RTTI support
::add_skill<pro::skills::format> // Formatting support
::add_convention<pro::operator_dispatch<"+">,
pro::facade_aware_overload_t<BinaryOverload>> // Recursive operator
::build {};
int main() {
pro::proxy<Addable> p1 = pro::make_proxy<Addable>(1);
pro::proxy<Addable> p2 = pro::make_proxy<Addable>(2);
pro::proxy<Addable> p3 = *p1 + *p2; // Uses facade-aware overload
std::cout << std::format("{}\n", *p3); // Prints "3"
}
请查看facade_aware_overload_t文档了解详细信息。
memcpy 移动的类型,默认情况下可实现更快的移动和赋值。这意味着你能获得更好的性能,还能减少样板代码。更多详情请参阅 is_bitwise_trivially_relocatable 文档。.ixx 文件,可实现极快的构建速度和更好的 IDE 支持。升级小型组件通常很简单,但迁移单体仓库或多模块产品可能颇具挑战性。请遵循以下指南:
pro::v3、pro::v4 等)。当一个翻译单元涉及多个主版本时,需显式限定命名空间:
pro::v3::foo(); // Proxy 3 API
pro::v4::foo(); // Proxy 4 API
最新版本将其命名空间重新导出为内联(默认)命名空间,因此迁移完成后,非限定调用(pro::foo())会解析到最新版本。
PRO4_DEF_MEM_DISPATCH。当同一翻译单元中包含来自多个专业的头文件时,请使用这些形式。这些规则让新旧代码能够在过渡期间共存,同时避免违反单定义规则(ODR)。
PRO_DEF_WEAK_DISPATCH 已被移除,取而代之的是更灵活的 weak_dispatch 类。proxiable_ptr_constraints 已合并到 ProFacade 要求中。access_proxy 现在被 proxy_invoke 和 proxy_reflect 遮蔽。Proxy 4 建立在 Proxy 3 中推出并经过验证的成熟基础之上,它在不重塑模型的前提下进行了针对性的优化。
核心功能(在 Proxy 3 中确立,且在日常使用中仍处于核心地位):
make_proxy(尽可能内联)、allocate_proxy(自定义分配器)、原始指针绑定、唯一所有权,以及通过 add_convention / add_reflection / add_facade 实现抽象的组合。proxy类型具备全生命周期通用性:同一外观可透明地支持非拥有、唯一、内联或外部管理的对象。针对 Proxy 4 的优化:
proxy_view、weak_proxy)。make_proxy_shared、allocate_proxy_shared)是对使用频率更高的 make_proxy/allocate_proxy 路径的补充(而非替代)。proxiable_target、inplace_proxiable_target)明确了类型可与 make_proxy 还是 make_proxy_inplace 配合使用的时机,从而提供更早、更精准的诊断信息,而非模板相关的杂乱提示。facade_aware_overload_t 支持递归的外观/运算符定义(例如返回相同外观的算术运算),且无需强制提前实例化。weak_dispatch 用于在某些包含的类型缺少约定时实现优雅降级。is_bitwise_trivially_relocatable)、模块支持以及更精简的代码生成。欢迎提出问题和反馈!如果您发现内容不清晰、存在漏洞或文档有缺失,欢迎提交问题或发起拉取请求。
文章翻译于 | Mingxin Wang Senior Software Engineer