作者 | 庇护所之主 编辑 | 自动驾驶之心
原文链接:https://www.zhihu.com/question/21376384/answer/3459052295
点击下方卡片,关注“自动驾驶之心”公众号
戳我-> 领取自动驾驶近15个方向学习路线
本文只做学术分享,如有侵权,联系删文
自动驾驶之心+自动驾驶之薪+具身智能之心知识星球 | 双十一活动限时7折
微软的proxy库
只有一个头文件,不到一千行的代码量
初见只觉神奇,不用继承就可以做运行时的各种抽象
用过一段时间之后感觉深不可测,小小的库完整实现了运行时多态所需的各种设施,包括重载、异常、反射等等,全方位碾压虚函数
初看代码感觉逻辑密度极高,有种指点江山的既视感
细品代码发现有很多匪夷所思的高难度体操,离奇而不失优雅
放几个片场给大家品鉴
片场1
template <template <class, class> class R, class O, class... Is>
struct recursive_reduction : std::type_identity<O> {};
template <template <class, class> class R, class O, class I, class... Is>
struct recursive_reduction<R, O, I, Is...>
: recursive_reduction<R, typename R<O, I>::type, Is...> {};
template <template <class, class> class R, class O, class... Is>
using recursive_reduction_t = typename recursive_reduction<R, O, Is...>::type;
这简单几行代码就实现了任意个数类型的自动化推导。代码中总共有两处应用,其中一处实现了把任意嵌套的类似tuple的类型展平并去重:
template <class O, class I> struct flat_reduction : std::type_identity<O> {};
template <class O, class... Is>
struct flat_reduction_impl : recursive_reduction<flat_reduction, O, Is...> {};
template <class... Os, class I>
requires(!is_tuple_like_well_formed<I>() && (!std::is_same_v<I, Os> && ...))
struct flat_reduction<std::tuple<Os...>, I>
: std::type_identity<std::tuple<Os..., I>> {};
template <class O, class I> requires(is_tuple_like_well_formed<I>())
struct flat_reduction<O, I> : instantiated_t<flat_reduction_impl, I, O> {};
其中 instantiated_t 可以用一个类似 tuple 的类型来实例化一个给定的类模板:
template <template <class...> class T, class TL, class Is, class... Args>
struct instantiated_traits;
template <template <class...> class T, class TL, std::size_t... Is,
class... Args>
struct instantiated_traits<T, TL, std::index_sequence<Is...>, Args...>
{ using type = T<Args..., std::tuple_element_t<Is, TL>...>; };
template <template <class...> class T, class TL, class... Args>
using instantiated_t = typename instantiated_traits<
T, TL, std::make_index_sequence<std::tuple_size_v<TL>>, Args...>::type;
有了这些基础设施,这个库就可以在编译时接受任意嵌套组合的抽象了!
例如:
PRO_DEF_FACADE(F1, std::tuple<A, B, C>);
PRO_DEF_FACADE(F2, std::tuple<A, std::tuple<B, C>>);
PRO_DEF_FACADE(F3, std::tuple<std::pair<A, B>, std::pair<B, C>>);
在编译时是等价的!
这就意味着以前使用虚函数时需要极力避免的菱形继承在使用这个库的时候完全不是问题,因为这个信息根本不会被编译到程序中!
片场2
template <class Expr>
consteval bool is_consteval(Expr)
{ return requires { typename std::bool_constant<(Expr{}(), false)>; }; }
第一次看这几行我完全不知道是做什么的,询问了 GPT 之后才大概理解微软的鬼斧神工!
简单来说,这个函数使用了 C++20 引入的 consteval 函数(编译时函数),可以用来判断任意一个表达式能否在编译时被计算!
乍看之下,这里的返回值是检测 std::bool_constant<false>
是否是一个类型,显得非常多此一举;但实际上, std::bool_constant
和 false
都是障眼法,这里的意图是测试 Expr
是否可以在非类型模板参数实例化的上下文中被计算,以此来判断 Expr
是否是一个可以在编译时计算的表达式!
看看这个函数是怎么被使用的:
template <class R, class P>
consteval bool is_reflection_type_well_formed() {
if constexpr (std::is_void_v<R>) {
return true;
} else if constexpr (std::is_constructible_v<R, std::in_place_type_t<P>>) {
return is_consteval([] { return R{std::in_place_type<P>}; });
}
return false;
}
简单一个函数就可以判断一个反射类型是否可以在编译时被实例化!可以说非常硬核了。
片场3
注意到里面有这么一个不起眼的类:
template <bool NE, class R, class... Args>
struct overload_traits_impl : applicable_traits {
template <class D>
struct meta_provider {
template <class P>
static constexpr func_ptr_t<NE, R, const char*, Args...> get() {
if constexpr (invocable_dispatch<
D, typename ptr_traits<P>::target_type, NE, R, Args...>) {
return &dispatcher_impl<P, typename D::template invoker<
typename ptr_traits<P>::target_type>, NE, R, Args...>;
} else {
return &dispatcher_default_impl<
typename D::template invoker<void>, NE, R, Args...>;
}
}
};
// ...
};
仔细观察会发现这个 get
函数返回的是一个函数指针。这里的 if
分支返回的函数重载与 P
有关,而 else
分支返回的类型是无关的。
这可以让编译器在生成虚表的时候做极限的空间优化!
这个库还有很多其他的实现细节,我目前还没太搞懂,但总体来看是个把 C++ 的模板元编程发挥到极致的一个神作了!
『自动驾驶之心知识星球』欢迎加入交流!重磅,自动驾驶之心科研论文辅导来啦,申博、CCF系列、SCI、EI、毕业论文、比赛辅导等多个方向,欢迎联系我们!
① 全网独家视频课程
端到端自动驾驶、仿真测试、自动驾驶C++、BEV感知、BEV模型部署、BEV目标跟踪、毫米波雷达视觉融合、多传感器标定、多传感器融合、多模态3D目标检测、车道线检测、轨迹预测、在线高精地图、世界模型、点云3D目标检测、目标跟踪、Occupancy、CUDA与TensorRT模型部署、大模型与自动驾驶、NeRF、语义分割、自动驾驶仿真、传感器部署、决策规划、轨迹预测等多个方向学习视频(扫码即可学习)
② 国内首个自动驾驶学习社区
国内外最大最专业,近4000人的交流社区,已得到大多数自动驾驶公司的认可!涉及30+自动驾驶技术栈学习路线,从0到一带你入门自动驾驶感知(端到端自动驾驶、世界模型、仿真闭环、2D/3D检测、语义分割、车道线、BEV感知、Occupancy、多传感器融合、多传感器标定、目标跟踪)、自动驾驶定位建图(SLAM、高精地图、局部在线地图)、自动驾驶规划控制/轨迹预测等领域技术方案、大模型,更有行业动态和岗位发布!欢迎扫描下方二维码,加入自动驾驶之心知识星球,这是一个真正有干货的地方,与领域大佬交流入门、学习、工作、跳槽上的各类难题,日常分享论文+代码+视频
![d9d6d85fd02dac11be7cfb588f8edc6e.png](https://img-blog.csdnimg.cn/img_convert/d9d6d85fd02dac11be7cfb588f8edc6e.png)
③【自动驾驶之心】技术交流群
自动驾驶之心是首个自动驾驶开发者社区,聚焦感知、定位、融合、规控、标定、端到端、仿真、产品经理、自动驾驶开发、自动标注与数据闭环多个方向,目前近60+技术交流群,欢迎加入!扫码添加汽车人助理微信邀请入群,备注:学校/公司+方向+昵称(快速入群方式)
④【自动驾驶之心】全平台矩阵