Advertisement
Guest User

C++ generic multidimensional array 2

a guest
Apr 25th, 2019
111
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.41 KB | None | 0 0
  1. #include <array>
  2. #include <vector>
  3. #include <type_traits>
  4.  
  5. template <size_t D, class T> class Array final {
  6. public:
  7.     template <class... Is,
  8.               class = std::enable_if_t<(... && std::is_convertible_v<size_t, Is>)>>
  9.     Array(Is &&... indices) :
  10.         _size({ std::forward<Is>(indices)... }),
  11.         _index(_size)
  12.     {
  13.         size_t total_size = 1;
  14.         for (size_t i = 0; i < _size.size(); ++i) {
  15.             total_size *= _size[i];
  16.         }
  17.  
  18.         _data.resize(total_size);
  19.     }
  20.  
  21.     Array(Array<D, T> const &) = default;
  22.     Array(Array<D, T> &&) = default;
  23.     ~Array() = default;
  24.  
  25.     Array<D, T> &operator=(Array<D, T> const &) = default;
  26.     Array<D, T> &operator=(Array<D, T> &&) = default;
  27.  
  28.     size_t size(size_t ix) const {
  29.         return _size[ix];
  30.     }
  31.  
  32.     size_t total_size() const {
  33.         return _data.size();
  34.     }
  35.  
  36.     template <class... Index> T &at(Index &&... indices) {
  37.         return _data.at(_index.compute(std::forward<Index>(indices)...));
  38.     }
  39.  
  40.     template <class... Index> T const &at(Index &&... indices) const {
  41.         return _data.at(_index.compute(std::forward<Index>(indices)...));
  42.     }
  43.  
  44.     template <class... Index> T &at_unchecked(Index &&... indices) {
  45.         return _data[_index.compute(std::forward<Index>(indices)...)];
  46.     }
  47.  
  48.     template <class... Index> T const &at_unchecked(Index &&... indices) const {
  49.         return _data[_index.compute(std::forward<Index>(indices)...)];
  50.     }
  51.  
  52.     auto begin() -> decltype(auto) {
  53.         return _data.begin();
  54.     }
  55.     auto begin() const -> decltype(auto) {
  56.         return _data.begin();
  57.     }
  58.     auto end() -> decltype(auto) {
  59.         return _data.end();
  60.     }
  61.     auto end() const -> decltype(auto) {
  62.         return _data.end();
  63.     }
  64.  
  65.     T *data() {
  66.         return _data.data();
  67.     }
  68.     T const *data() const {
  69.         return _data.data();
  70.     }
  71.  
  72. private:
  73.     class LinearIndex {
  74.     public:
  75.         LinearIndex(std::array<size_t, D> const& size);
  76.  
  77.         template <class... Index>
  78.         size_t compute(Index&&... index) const;
  79.     private:
  80.         template <class... Index, size_t... Dimension>
  81.         size_t _compute_helper(std::integer_sequence<size_t, Dimension...>, Index&&... index) const;
  82.  
  83.         constexpr size_t _get_factor(size_t i) const {
  84.             if ((i+1) < D) {
  85.                 return _factor[i];
  86.             } else {
  87.                 return 1;
  88.             }
  89.         }
  90.  
  91.         std::array<size_t, D - 1> _factor;
  92.     };
  93.  
  94.     std::array<size_t, D> _size;
  95.     std::vector<T> _data;
  96.     LinearIndex _index;
  97. };
  98.  
  99. template <size_t D, class T>
  100. Array<D,T>::LinearIndex::LinearIndex(std::array<size_t, D> const& size) {
  101.     size_t factor = 1;
  102.     for (size_t i = size.size() - 1; i > 0; --i) {
  103.         factor *= size[i];
  104.         _factor[i - 1] = factor;
  105.     }
  106. }
  107.  
  108. template <size_t D, class T>
  109. template <class... Index>
  110. size_t Array<D,T>::LinearIndex::compute(Index&&... index) const {
  111.     static_assert(sizeof...(Index) == D, "wrong number of indices.");
  112.  
  113.     return _compute_helper(
  114.         std::index_sequence_for<Index...>{},
  115.         std::forward<Index>(index)...);
  116. }
  117.  
  118. template <size_t D, class T>
  119. template <class... Index, size_t... Dimension>
  120. size_t Array<D,T>::LinearIndex::_compute_helper(
  121.     std::integer_sequence<size_t, Dimension...>,
  122.     Index&&... index) const
  123. {
  124.     return (... + (_get_factor(Dimension)*index));
  125. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement