如何为定长数组重载operator|运算符?相关模板代码解析
嘿,我来帮你理顺这两个问题哈~
一、如何为定长数组重载
operator|运算符 要给定长数组重载operator|,核心是避免数组退化为指针的问题,得用模板捕获数组的长度。结合你给的适配器思路,咱们可以这么实现:
首先先定义目标转换类型(比如你代码里的foo_t):
template <typename T, int N> struct foo_t { std::array<T, N> elements; // 从定长数组初始化 foo_t(const T (&src)[N]) { std::copy(std::begin(src), std::end(src), elements.begin()); } };
然后按照适配器框架适配定长数组,最终实现管道式操作:
// 适配器标记类,用来识别适配器操作 template <typename Adapter> struct template_adapter_t {}; // 针对长度N的foo适配器 template <int N> struct foo_adapter_t { // 适配定长数组到foo_t template <typename T> static foo_t<T, N> adapt(const T (&arr)[N]) { return foo_t<T, N>(arr); } }; // 工厂函数,生成适配器标记对象 template <int N> template_adapter_t<foo_adapter_t<N>> foo() { return {}; } // 重载operator|,让定长数组支持管道式适配 template <typename T, int N, typename Adapter> auto operator|(const T (&arr)[N], template_adapter_t<Adapter>(*)()) -> decltype(Adapter::adapt(arr)) { return Adapter::adapt(arr); }
这样你就能用简洁的管道语法调用了:
int my_arr[3] = {10, 20, 30}; auto result = my_arr | foo<3>(); // result是foo_t<int,3>类型
二、你给出的模板代码的作用
咱们先把代码贴出来,再逐个拆解:
template <typename T> struct template_adapter_t {}; template <int N> struct foo_adapter_t { template <typename T> static foo_t<T, N> adapt(T const&); }; template <int N> template_adapter_t< foo_adapter_t<N> > foo(); template <typename Range, typename Adapter> auto operator|( Range const& range, template_adapter_t<Adapter>(*)()) -> decltype(Adapter::adapt(range)) { return Adapter::adapt(range); }
这其实是一套通用的管道式适配器框架,每个部分的作用如下:
template_adapter_t<T>:这是个空的「标记类」,用来给适配器打标签,让operator|能识别出这是一个适配器操作,而非普通函数或值。它的模板参数就是具体的适配器类型(比如foo_adapter_t<5>)。foo_adapter_t<N>:这是针对长度N的具体适配器类。里面的static adapt方法是核心逻辑——它接收一个范围类型(比如定长数组、std::array甚至其他容器),把它转换成foo_t<T, N>类型的对象,T会自动从传入的range推导出来。foo()工厂函数:这是个语法糖,当你写foo<5>()时,会返回一个template_adapter_t<foo_adapter_t<5>>类型的对象,用来触发后面的operator|重载。- 最后的
operator|重载:这是整个框架的粘合代码。它接收一个范围(比如你的定长数组)和适配器标记的函数指针,调用适配器的adapt方法完成转换,返回对应的目标类型。
说白了,这套代码就是让你能用管道语法(range | adapter())实现类型转换,而且是通用的——你可以随便加其他适配器(比如bar_adapter_t),只要遵循同样的模式,就能复用这个operator|,不用每次都重载新的运算符。
举个实际使用的例子:
std::array<int, 4> arr = {1,2,3,4}; auto my_foo = arr | foo<4>(); // 调用foo_adapter_t<4>::adapt(arr),得到foo_t<int,4>
内容的提问来源于stack exchange,提问作者Matthew
相关产品推荐
相关产品推荐

