You could take arrays of an arbitrary number of dimensions by reference and peel off one layer at a time recursively.
Here's an example of a print function for demonstrational purposes:
#include <cstddef>
#include <iostream>
#include <iterator>
#include <string>
#include <type_traits>
template <class T, std::size_t N>
void print(const T (&arr)[N], unsigned indent = 0) {
    if constexpr (std::rank_v<T> == 0) {
        // inner layer - print the values:
        std::cout << std::string(indent, ' ') << '{';
        auto it = std::begin(arr);
        std::cout << *it;
        for (++it; it != std::end(arr); ++it) {
            std::cout << ", " << *it;
        }
        std::cout << '}';
    } else {
        // still more layers to peel off:
        std::cout << std::string(indent, ' ') << "{\n";
        auto it = std::begin(arr);
        print(*it, indent + 1);
        for (++it; it != std::end(arr); ++it) {
            std::cout << ",\n";
            print(*it, indent + 1);
        }
        std::cout << '\n' << std::string(indent, ' ') << '}';
    }
}
Here's a usage example with a 3 dimensional array:
int main() {
    int array[2][3][5]
    {
        {
            {1, 2, 9, -5, 3},
            {6, 7, 8, -45, -7},
            {11, 12, 13, 14, 25}
        },
        {
            {4, 5, 0, 33, 34},
            {8, 9, 99, 54, 44},
            {14, 15, 16, 19, 20}
        }
    };
    print(array);
}
... which will produce this output:
{
 {
  {1, 2, 9, -5, 3},
  {6, 7, 8, -45, -7},
  {11, 12, 13, 14, 25}
 },
 {
  {4, 5, 0, 33, 34},
  {8, 9, 99, 54, 44},
  {14, 15, 16, 19, 20}
 }
}