So, here's one way of doing it:
#include <algorithm>
#include <array>
#include <cstddef>
#include <cstdio>
#include <type_traits>
// array_type_swap convert T[a][b][c][...] to Y[a][b][c][...] for arbitrary
// dimensions
template <class T, class Y>
struct array_type_swap {
using type = T;
};
template <class T, class Y, std::size_t N>
struct array_type_swap<T, std::array<Y, N>> {
using type = std::array<typename array_type_swap<T, Y>::type, N>;
};
template <class T, class Y, std::size_t N>
struct array_type_swap<T, Y[N]> {
using type = typename array_type_swap<T, std::array<Y, N>>::type;
};
template <class T, class Y>
using array_type_swap_t = typename array_type_swap<T, Y>::type;
template <class>
inline constexpr bool is_std_array_v = false;
template <class T, std::size_t N>
inline constexpr bool is_std_array_v<std::array<T, N>> = true;
// Get element count of a std::array, or C style array as constexpr. The value
// is 1 for all other types (as in array of 1).
template <class T>
struct contexpr_array_size {
static std::size_t constexpr size = 1;
};
template <class T, std::size_t N>
struct contexpr_array_size<T[N]> {
static std::size_t constexpr size = N;
};
template <class T, std::size_t N>
struct contexpr_array_size<std::array<T, N>> {
static std::size_t constexpr size = N;
};
template <class T>
inline auto constexpr contexpr_array_size_v = contexpr_array_size<T>::size;
template <class T, class Y>
void copy_array(T& dst, Y const& src) {
static_assert(contexpr_array_size_v<T> == contexpr_array_size_v<Y>,
"Can only copy arrays of the same size");
if constexpr (!is_std_array_v<Y> && !std::is_array_v<Y>)
dst = static_cast<T>(src);
else
for (std::size_t i = 0; i < contexpr_array_size_v<Y>; ++i)
copy_array(dst[i], src[i]);
}
template <class T, class Y>
auto uniform(Y const& arr) {
array_type_swap_t<T, Y> result;
copy_array(result, arr);
return result;
}
int main() {
std::puts("built-in array :");
const int a[2][3] = {{1, 2, 3}, {4, 5, 6}};
auto b = uniform<float>(a);
for (auto& row : b) {
for (auto& elm : row) std::printf("%.2f ", elm);
std::putchar('\n');
}
std::puts("\nstd::array :");
std::array<std::array<int, 3>, 2> stdarr = {{{6, 5, 4}, {3, 2, 1}}};
b = uniform<float>(stdarr);
for (auto& row : b) {
for (auto& elm : row) std::printf("%.2f ", elm);
std::putchar('\n');
}
}