查看原文
其他

如何优雅的实现多维数组

程序喵大人 程序喵大人 2022-08-22

数组,想必大家都知道,大体长这样:

int native_arr[3];std::array<int, 3> arr;


那二维数组呢,假如我需要定义一个3行4列的数组,是不是这样:

int multi_array_native[3][4];std::array<std::array<int, 3>, 4> multi_array;

第一眼看上去,貌似没啥毛病。


但其实不对,上面的multi_array其实是个4行3列的数组,然而这才是个正确的3行4列的数组:

std::array<std::array<int, 4>, 3> multi_array;

这块其实就很容易写出不容易发现的bug,可能二维数组还好一些,如果是多维数组,更难办。


那有没有办法,正常的使用std::array实现多维数组呢?


肯定有,就是利用好模板元编程技巧,这里先来实现个二维数组:

template <typename T, size_t R, size_t C>using TwoDimMatrix = std::array<std::array<T, C>, R>;


其实就是将反直觉的R和C调换个顺序,使用方式如下:

void test_two_dim_matrix() { constexpr size_t row = 2; constexpr size_t col = 3; TwoDimMatrix<int, row, col> mat; int k = 0; for (int i = 0; i < row; ++i) { for (int j = 0; j < col; ++j) { mat[i][j] = ++k; } }}

使用TwoDimMatrix,就可以正常的定义二维数组,而无需反常规的按相反顺序定义数组。


定义好了二维数组,那三维、四维、五维数组如何定义?难道要像上面一样,定义出ThreeDimMatrix、FourDimMatrix?


肯定不能这样,那可是太麻烦了,也不通用。


这里可能利用模板的可变参数来实现,直接上代码吧:

template <typename T, size_t R, size_t... C>struct Matrix { using Col = typename Matrix<T, C...>::type; using type = std::array<Col, R>;};
template <typename T, size_t R>struct Matrix<T, R> { using type = std::array<T, R>;};


使用方式如下:

void test_multi_array() { constexpr size_t a = 2; constexpr size_t b = 3; constexpr size_t c = 4; constexpr size_t d = 5; Matrix<int, a, b, c, d>::type mat; int u = 0; for (int i = 0; i < a; ++i) { for (int j = 0; j < b; ++j) { for (int k = 0; k < c; ++k) { for (int m = 0; m < d; ++m) { mat[i][j][k][m] = ++u; } } } }}

看,这样就方便多了吧,这样就可以使用常规的方式定义正确的多维数组啦。


希望这个小技巧能对大家有所帮助。



往期推荐



有没有比友元更优雅的方式

C++服务性能优化的道与术-道篇:阿姆达尔定律

压箱底的音视频学习资料以及面经整理

C++ Best Practices (C++最佳实践)翻译与阅读笔记

2021程序喵技术年货

SDK开发的一些思考

【线上问题】P1级公司故障,年终奖不保

C++的全链路追踪方案,稍微有点高端

多线程程序中操作的原子性

喵哥吐血整理:软件开发的51条建议

模版定义一定要写在头文件中吗?

四万字长文,这是我见过最好的模板元编程文章!

如何正确的理解指针和结构体指针、指针函数、函数指针这些东西?

【性能优化】高效内存池的设计与实现

介绍一个C++中非常有用的设计模式



您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存