如何在Rust中获取多维数组的秩及各维度大小(对应C++ std::rank/std::extent)
Rust中获取多维数组的秩与各维度大小
在Rust中,没有像C++的std::rank和std::extent那样直接的标准库工具,但可以通过自定义 trait + 递归实现来完成编译时的维度数量(秩)和各维度大小的获取——因为Rust的多维数组本质是嵌套的固定大小数组(比如[[i32; 2]; 3]代表3个元素,每个元素是长度为2的i32数组)。
一、获取数组的秩(维度数量)
定义一个带关联常量的trait,递归计算嵌套数组的深度:
// 定义计算秩的trait trait Rank { const RANK: usize; } // 非数组类型的秩为0 impl<T> Rank for T { default const RANK: usize = 0; } // 数组类型的秩为 1 + 内部元素的秩 impl<T, const N: usize> Rank for [T; N] { const RANK: usize = 1 + <T as Rank>::RANK; } // 使用示例 fn main() { type Array1 = [i32; 5]; type Array2 = [[i32; 2]; 3]; type Array3 = [[[i32; 4]; 2]; 3]; assert_eq!(<Array1 as Rank>::RANK, 1); assert_eq!(<Array2 as Rank>::RANK, 2); assert_eq!(<Array3 as Rank>::RANK, 3); }
二、获取指定维度的大小(对应std::extent)
同样通过自定义trait,递归提取对应维度的长度:
// 定义获取指定维度大小的trait trait Extent<const IDX: usize> { const EXTENT: usize; } // 当索引超过数组维度时,返回0(和C++ std::extent行为一致) impl<T, const IDX: usize> Extent<IDX> for T { default const EXTENT: usize = 0; } // 索引为0时,返回当前数组的长度 impl<T, const N: usize> Extent<0> for [T; N] { const EXTENT: usize = N; } // 索引大于0时,递归获取内部数组对应索引-1的长度 impl<T, const N: usize, const IDX: usize> Extent<IDX> for [T; N] where T: Extent<{IDX - 1}>, { const EXTENT: usize = <T as Extent<{IDX - 1}>>::EXTENT; } // 使用示例 fn main() { type Array2 = [[i32; 2]; 3]; type Array3 = [[[i32; 4]; 2]; 3]; // Array2的第0维长度是3,第1维是2,第2维是0(超出维度) assert_eq!(<Array2 as Extent<0>>::EXTENT, 3); assert_eq!(<Array2 as Extent<1>>::EXTENT, 2); assert_eq!(<Array2 as Extent<2>>::EXTENT, 0); // Array3的第0维3,第1维2,第2维4,第3维0 assert_eq!(<Array3 as Extent<0>>::EXTENT, 3); assert_eq!(<Array3 as Extent<1>>::EXTENT, 2); assert_eq!(<Array3 as Extent<2>>::EXTENT, 4); assert_eq!(<Array3 as Extent<3>>::EXTENT, 0); }
注意事项
- 以上实现都是编译时计算,不会带来运行时开销,和C++的模板元编程行为一致。
- 仅适用于Rust的固定大小数组(
[T; N]),对于动态数组(Vec<Vec<T>>),需要在运行时通过.len()方法逐层获取长度——因为动态数组的大小是运行时确定的。
内容的提问来源于stack exchange,提问作者Harry
相关产品推荐
相关产品推荐

