Q:

Treat nested std::arrays as a single flat array with chained .data()

Let's say I have this little fixed-dimension matrix class:
template<size_t M, size_t N>
struct MatMN { 
  std::array<std::array<double, N>, M> rows;
  double* begin() { return rows.data()->data(); } //The scary part
  double* end() { return begin() + M*N; }
  //const iterators, etc.
};

and instead of using nested loops, I implement scalar multiplication (also equality testing, binary de/serialization, etc.) like so:
template<size_t M, size_t N>
MatMN<M, N> operator*(double scalar, MatMN<M, N> mat) {
  for (double& x_ : mat) { x_ *= scalar; }
  return mat;
}

Is it actually okay to treat nested std::arrays as a single flat C-style array by using .data()->data()?
Am I at risk of some strict-aliasing issue?  Or maybe unexpected struct padding at the end of individual std::arrays (i.e. between matrix rows)?  So far it's worked fine for me (with GCC), but I know that doesn't mean much in C++.

A:

Is it actually okay to treat nested std::arrays as a single flat C-style array by using .data()->data()?

No.  std::array is allowed to have padding at the end.  That means that there could be a gap between where one array ends and the other begins in the nested structure.  getting a pointer like you do would (if the padding is there) will cause you to access that padding giving you undefined results.
Instead of storing the matrix in a 2d std::array you should just use a 1d std::array.  That way you can guarantee the elements are all next to each other in memory.

