2D counterpart of std::array in C++17
Let me collect a couple of thoughts here.


Aggregate initialization currently works like this:

array2d&lt;int, 2, 2&gt; a{{1, 2, 3, 4}};


but wouldn't it be favorable to allow for

array2d&lt;int, 2, 2&gt; a{{1, 2}, {3, 4}};

std::array::at performs bound checking and throws upon an out of bounds index. When your intention is to stick with the std::array interface, you should do the same.
If you want the container to be standard-compliant, there are some type aliases missing and maybe more. In particular, there are no cbegin(), cend(), crbegin(), crend() member functions. Is this intended?
You implicitly use row-major order. Are you sure everyone expects this? Users familiar with Eigen and their fixed size matrices might at least want to customize row-/column-major ordering, e.g. Eigen::Matrix&lt;int, 2, 2, Eigen::ColMajor&gt; m;
A range based for loop will considerably differ from a manual loop over rows and columns. Example:

// Loop over elements, transposed access. Requires nested loop.
for (std::size_t i = 0; i &lt; 2; ++i)
   for (std::size_t j = 0; j &lt; 2; ++j)
      std::cout &lt;&lt; a[j][i] &lt;&lt; "\n";

// Loop over elements, tranposed access impossible. Only one loop.
for (const auto&amp; i : d)
    std::cout &lt;&lt; i &lt;&lt; "\n";


This is slightly unintuitive. Shouldn't the range based for loop require a nested loop as well?
The static data member sizes is not used anywhere.


Getting a two-dimensional array to work is not that much of an effort. Getting the semantics right is hard. Sticking to the std::array interface is a good goal when ease of use is intended for those familiar with the std::array template. But the additional dimension pulls in requirements that can't be tackled with the concepts of std::array. I would recommend having a look at established linear algebra libraries and their fixed size matrices. Also, the mdspan proposal for a multi-dimensional view on array types might be a good read.