相信读者朋友们读过很多设计精妙的C++开源代码,读到深处,理解作者的设计意图后,不禁手舞足蹈,拍案叫绝,感觉自己跟心中敬仰的大神的思想又近了一步,这不,最近读到微软的一个proxy库,只有一个头文件,不到一千行的代码量。初见只觉神奇,不用继承就可以做运行时的各种抽象,用过一段时间之后感觉深不可测,小小的库完整实现了运行时多态所需的各种设施,包括重载、异常、反射等等,全方位碾压虚函数。初看代码感觉逻辑密度极高,有种指点江山的既视感。细品代码发现有很多匪夷所思的高难度体操,离奇而不失优雅。
放几个片场给大家品鉴
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>>);
在编译时是等价的!
这就意味着以前使用虚函数时需要极力避免的菱形继承在使用这个库的时候完全不是问题,因为这个信息根本不会被编译到程序中!
template <class Expr>
consteval bool is_consteval(Expr)
{>; }; }
第一次看这几行我完全不知道是做什么的,询问了 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;
}
简单一个函数就可以判断一个反射类型是否可以在编译时被实例化!可以说非常硬核了。
注意到里面有这么一个不起眼的类:
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++ 的模板元编程发挥到极致的一个神作了!
联系客服