If you want to do make an implementation that supports runtime-specified matrix sizes you change your implementation from...
auto *my_matrix = new MathArray<double, 10, 10>();
Into
auto *my_matrix = new MathArray<double>(10, 10);
Most programs don't need dynamically sized arrays (rows and columns) and as such it makes sense to also provide a template Row and Column width. By doing this you can likely implement matrix multiplication and addition as a constexpr (with some effort) and thus get....
1. Compile time matrix evaluation
2. Vectorized multiplication/addition of matrices
3. Pipline-efficient code
But otherwise, great. Now if you just add slicing so that if we, say
and then say fill in the matrix by then should return and then we're talking. (Slicing should of course also work in higher dimensions than 2.)