#include <iostream>
#include <array>
template <typename T, size_t Rows, size_t Cols>
class Matrix {
protected:
std::array<std::array<T, Cols>, Rows> matrix;
public:
constexpr Matrix() = default;
constexpr explicit Matrix(std::array<std::array<T, Cols>, Rows> matrix) : matrix(std::move(matrix)) { }
consteval Matrix(std::initializer_list<std::initializer_list<T>> matrix) : matrix() {
if (matrix.size() != Rows) {
throw std::invalid_argument("Invalid matrix Rows count");
}
auto current_row = matrix.begin();
for (size_t i = 0; i < matrix.size(); i++, current_row++) {
if (current_row->size() != Cols) {
throw std::invalid_argument("Invalid matrix column count");
}
std::copy(current_row->begin(), current_row->end(), this->matrix[i].begin());
}
}
constexpr auto& operator[](this auto&& self, size_t index) { return self.matrix[index]; }
};
template <typename T, size_t N>
struct Vector : Matrix<T, 1, N> {
using Matrix<T, 1, N>::Matrix;
template <typename U, typename... Us>
consteval explicit Vector(U u, Us... us) {
this->matrix[0] = { u, us... };
}
constexpr auto& operator[](this auto&& self, size_t index) { return self.matrix[0][index]; }
};
template <typename T, typename... U>
Vector(T, U...) -> Vector<T, 1 + sizeof...(U)>;
int main() {
constexpr Matrix<int, 4, 3> matrix {
{ 1, 2, 3 },
{ 1, 2, 3 },
{ 1, 2, 3 },
{ 1, 2, 3 }
};
static_assert(matrix[2][1] == 2);
constexpr Vector v { 1, 2, 3 };
static_assert(v[1] == 2);
}
在这里,为向量类编写推导指南以避免指定类型和元素数量是很容易的,但是当涉及到
Matrix
类时,这就相当具有挑战性了。这是因为传递的initializer_list的std::initializer_list::size
不是常量表达式,我无法从中推导出Cols
参数。
constexpr Matrix matrix {
{ 1, 2, 3 },
{ 1, 2, 3 },
{ 1, 2, 3 },
{ 1, 2, 3 }
};
constexpr Matrix<double> matrix {
{ 1, 2, 3 },
{ 1, 2, 3 },
{ 1, 2, 3 },
{ 1, 2, 3 }
};
您可以添加数组的推导指南:
template <class T, size_t R, size_t C>
Matrix(const T(&arr)[R][C]) -> Matrix<T, R, C>;
...并且您需要一组额外的支架才能使用它:
constexpr Matrix matrix {{
{ 1, 2, 3 },
{ 1, 2, 3 },
{ 1, 2, 3 },
{ 1, 2, 3 }
}};