fork download
  1. // Two-dimensional array with dimensions determined at runtime
  2. //
  3. // Written in 2012 by Martinho Fernandes
  4. //
  5. // To the extent possible under law, the author(s) have dedicated all copyright and related
  6. // and neighboring rights to this software to the public domain worldwide. This software is
  7. // distributed without any warranty.
  8. //
  9. // You should have received a copy of the CC0 Public Domain Dedication along with this software.
  10. // If not, see <http://c...content-available-to-author-only...s.org/publicdomain/zero/1.0/>.
  11.  
  12. // Installation:
  13. // Place this into a header file and #include it in your code. Done.
  14. //
  15. // Usage:
  16. // so::darray<int> x(10, 10); // create a 10x10 array
  17. // int x12 = x[1][2]; // access an element
  18. // x[1][2] = 42; // modify an element
  19. // int* all = x.data(); // get a pointer to the whole array
  20. // int* row1p = x[1].data(); // get a pointer to a row
  21. // std::sort(x.begin(), x.end()); // use the whole array in standard library algorithms
  22. // std::sort(x[1].begin(), x[1].end()); // use a row in standard library algorithms
  23. // so::darray<int> y = x; // copiable
  24. // so::darray<int> z = std::move(x); // movable (C++11)
  25. //
  26. // This can also be easily and safely returned from functions by value, no need to use pointers or dynamic allocation:
  27. // so::darray2d<int> get_an_array(int x) {
  28. // so::darray2d<int> result(x, x);
  29. // return result;
  30. // }
  31. //
  32. // Only two-dimensional arrays are supported.
  33. // If you think you need a three-dimensional array, you're probably doing
  34. // it wrong. But if you really want to take a stab at doing so, you may use
  35. // this code as a starting point.
  36. //
  37. // If you don't want any C++11 features #define SO_ARRAY2D_NO_CPP11 before #including.
  38. //
  39. // Now, go forth and stop newing up multidimensional arrays
  40.  
  41. #ifndef DARRAY2D_HPP_INCLUDED
  42. #define DARRAY2D_HPP_INCLUDED
  43.  
  44. #include <cassert> // assert
  45. #include <cstddef> // size_t, ptrdiff_t
  46. #include <algorithm> // copy
  47.  
  48. #ifndef SO_ARRAY2D_NO_CPP11
  49. #define SO_ARRAY2D_CPP11_DELETE = delete
  50. #else
  51. #define SO_ARRAY2D_CPP11_DELETE
  52. #endif
  53.  
  54. #ifndef SO_ARRAY2D_NO_CPP11
  55. # include <memory> // unique_ptr
  56. #else
  57. # include <utility> // swap
  58. namespace so {
  59. namespace detail {
  60. template <typename T>
  61. class array_ptr {
  62. public:
  63. array_ptr(T* ptr) : ptr(ptr) { assert(ptr); }
  64. ~array_ptr() { delete[] ptr; }
  65.  
  66. T* get() const { return ptr; }
  67. T& operator[](std::ptrdiff_t index) const { return ptr[index]; }
  68.  
  69. void swap(array_ptr<T>& that) {
  70. using std::swap;
  71. swap(ptr, that.ptr);
  72. }
  73.  
  74. private:
  75. T* ptr;
  76.  
  77. array_ptr(array_ptr const&);
  78. array_ptr& operator=(array_ptr const&);
  79. };
  80. template <typename T>
  81. void swap(array_ptr<T>& x, array_ptr<T>& y) { x.swap(y); }
  82. }
  83. }
  84. #endif
  85.  
  86. namespace so {
  87. template <typename T>
  88. class darray2d {
  89. #ifndef SO_ARRAY2D_NO_CPP11
  90. typedef std::unique_ptr<T[]> smart_ptr;
  91. #else
  92. typedef detail::array_ptr<T> smart_ptr;
  93. #endif
  94. public:
  95. darray2d(std::size_t n, std::size_t m)
  96. : storage(new T[n*m]), n(n), m(m) {}
  97.  
  98. darray2d(darray2d const& that)
  99. : storage(new T[that.n*that.m]), n(that.n), m(that.m) {
  100. std::copy(that.begin(), that.end(), this->begin());
  101. }
  102. #ifndef SO_ARRAY2D_NO_CPP11
  103. darray2d(darray2d&& that)
  104. : storage(std::move(that.storage)), n(that.n), m(that.m) {
  105. that.n = that.m = 0;
  106. }
  107. #endif
  108. darray2d& operator=(darray2d that) {
  109. swap(*this, that);
  110. return *this;
  111. }
  112.  
  113. class proxy {
  114. public:
  115. T& operator[](std::ptrdiff_t index) {
  116. assert(index >= 0 && index < m);
  117. return storage[row * m + index];
  118. }
  119. T* begin() { return &storage[row * m]; }
  120. T* end() { return &storage[row * m] + m; }
  121. T* data() { return &storage[row * m]; }
  122.  
  123. private:
  124. template <typename X>
  125. void operator=(X const&) SO_ARRAY2D_CPP11_DELETE;
  126.  
  127. friend class darray2d<T>;
  128.  
  129. proxy(T* storage, std::ptrdiff_t row, std::size_t m)
  130. : storage(storage), row(row), m(m) {}
  131.  
  132. T* storage;
  133. std::ptrdiff_t row;
  134. std::size_t m;
  135. };
  136.  
  137. class const_proxy {
  138. public:
  139. T const& operator[](std::ptrdiff_t index) {
  140. assert(index >= 0 && index < m);
  141. return storage[row * m + index];
  142. }
  143. T const* begin() const { return &storage[row * m]; }
  144. T const* end() const { return &storage[row * m] + m; }
  145. T const* data() const { return &storage[row * m]; }
  146.  
  147. private:
  148. template <typename X>
  149. void operator=(X const&) SO_ARRAY2D_CPP11_DELETE;
  150.  
  151. friend class darray2d<T>;
  152.  
  153. const_proxy(T const* storage, std::ptrdiff_t row, std::size_t m)
  154. : storage(storage), row(row), m(m) {}
  155.  
  156. T const* storage;
  157. std::ptrdiff_t row;
  158. std::size_t m;
  159. };
  160.  
  161. proxy operator[](std::ptrdiff_t index) {
  162. assert(index >= 0 && index < n);
  163. return proxy(storage.get(), index, m);
  164. }
  165. const_proxy operator[](std::ptrdiff_t index) const {
  166. assert(index >= 0 && index < n);
  167. return const_proxy(storage.get(), index, m);
  168. }
  169. std::size_t rows() const { return n; }
  170. std::size_t columns() const { return m; }
  171.  
  172. T* begin() { return &storage[0]; }
  173. T* end() { return &storage[0] + n*m; }
  174. T* data() { return &storage[0]; }
  175. T const* begin() const { return &storage[0]; }
  176. T const* end() const { return &storage[0] + n*m; }
  177. T const* data() const { return &storage[0]; }
  178.  
  179. friend void swap(darray2d& x, darray2d& y) {
  180. using std::swap;
  181. swap(x.storage, y.storage);
  182. swap(x.n, y.n);
  183. swap(x.m, y.m);
  184. }
  185.  
  186. private:
  187. smart_ptr storage;
  188. std::size_t n;
  189. std::size_t m;
  190. };
  191. }
  192.  
  193. #undef SO_ARRAY2D_CPP11_DELETE
  194.  
  195. #endif
  196.  
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty