Boost logo

Boost :

From: Helmut Zeisel (HZ2012_at_[hidden])
Date: 2022-01-02 21:03:11


   Do you really need a nested array?

   You could also use a flat array and an adapter for the index, e,g,

   template<typename T, typename U>
   concept is_convertible_to = std::is_convertible_v<T, U>;

   template<typename T, typename Index>
   struct array_adapter
   {
       std::array<T, Index::size()> m_a;
       constexpr array_adapter(is_convertible_to<T> auto ... t) requires
   (sizeof...(t) == Index::size()): m_a{t ...} {}

       constexpr T operator()(is_convertible_to<std::size_t> auto ... i)
   const
       requires (sizeof...(i) == Index::dim())
       {
           return m_a[Index{}(i...)];
       }

       constexpr T& operator()(is_convertible_to<std::size_t> auto ... i)
       requires (sizeof...(i) == Index::dim())
       {
           return m_a[Index{}(i...)];
       }
   };

   For Index, you might e.g. use

   template<std::size_t ... N>
   struct row_major_index
   {
       static constexpr std::size_t size()
       {
           return (N*...);
       }
       template<std::size_t i>
       constexpr static std::size_t first(is_convertible_to<std::size_t>
   auto... n)
       {
           if constexpr(i == 0)
           {
              return std::get<0>(std::make_tuple(n...));
           }
           else
           {
              return
   std::get<i>(std::make_tuple(n...))+std::get<i>(std::make_tuple(N...))*f
   irst<i-1>(n...);
           }
       }
       constexpr std::size_t operator()(is_convertible_to<std::size_t>
   auto... n)
       {
           return first<sizeof...(n)-1>(n...);
       }
       static constexpr std::size_t dim()
       {
           return sizeof...(N);
       }
   };

   This can be used as follows:

   nt main()
   {
       static const int N1 = 2;
       static const int N2 = 3;
       static const int N3 = 4;
       array_adapter<double,
                     row_major_index<N1,N2,N3>>
       a{111.,112.,113.,114.,
         121.,122.,123.,124.,
         131.,132.,133.,134.,
         211.,212.,213.,214.,
         221.,222.,223.,224.,
         231.,232.,233.,234.};

       for(int n1=0; n1 != N1; ++n1)
       {
           for(int n2=0; n2!=N2; ++n2)
           {
              for(int n3=0; n3!=N3; ++n3)
              {
                 std::cout << "a(" << n1 << "," << n2 << "," << n3 << ")="
   << a(n1,n2,n3) << std::endl;
              }
           }
       }

       return 0;
   }

   Of course, this could be generaized to different types of arrays (e.g.
   std:.vecrtor) usng some policy class and

   template<typename T, typename Index, typename Policy> struct
   array_index_adapter { ... };

   Helmut


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk