如何優雅的實現多維數組
數組,想必大家都知道,大體長這樣:
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;
}
}
}
}
}
看,這樣就方便多了吧,這樣就可以使用常規的方式定義正確的多維數組啦。