fork download
  1. #include <iostream>
  2. #include <functional>
  3. #include <algorithm>
  4. #include <utility>
  5. #include <memory>
  6. #include <cstddef>
  7. #include <cassert>
  8.  
  9.  
  10. template<typename T>
  11. struct matrix {
  12.  
  13. template<typename V>
  14. struct index_proxy {
  15.  
  16. V & operator [](std::size_t const j) const {
  17. assert(index < ref.height());
  18. assert(j < ref.width());
  19.  
  20. return ref.data()[ref.width() * index + j];
  21. }
  22.  
  23. operator V &() const {
  24. assert(index < ref.size());
  25.  
  26. return ref.data()[index];
  27. }
  28.  
  29. template<typename S>
  30. void operator =(S && value) {
  31. assert(index < ref.size());
  32.  
  33. ref.data()[index] = std::forward<S>(value);
  34. }
  35.  
  36. private:
  37. friend class matrix;
  38.  
  39. index_proxy(matrix & ref, std::size_t const index) : ref(ref), index(index) {}
  40.  
  41. index_proxy(index_proxy const&) = delete;
  42. index_proxy(index_proxy &&) = delete;
  43.  
  44. matrix & ref;
  45. std::size_t const index;
  46. };
  47.  
  48.  
  49. matrix(std::size_t const height_, std::size_t const width_)
  50. : data_(new T[height_ * width_])
  51. , height_(height_)
  52. , width_(width_)
  53. {}
  54.  
  55. matrix(matrix const& other) : matrix(other.height(), other.width()) {
  56. std::copy_n(other.data(), size(), data());
  57. }
  58.  
  59. matrix(matrix && other)
  60. : data_(std::move(other.data_))
  61. , height_(other.height_)
  62. , width_(other.width_)
  63. {}
  64.  
  65. matrix & operator =(matrix const& other) {
  66. height_ = other.height();
  67. width_ = other.width();
  68.  
  69. if (size() != other.size()) {
  70. data().reset(new T[height() * width()]);
  71. }
  72.  
  73. std::copy_n(other.data(), size(), data());
  74.  
  75. return *this;
  76. }
  77.  
  78. matrix & operator =(matrix && other) {
  79. data_ = std::move(other.data_);
  80. height_ = other.height_;
  81. width_ = other.width_;
  82.  
  83. return *this;
  84. }
  85.  
  86.  
  87. index_proxy<T> operator [](std::size_t const index) {
  88. return {*this, index};
  89. }
  90. index_proxy<T const> operator [](std::size_t const index) const {
  91. return {*this, index};
  92. }
  93.  
  94.  
  95. std::size_t height() const {
  96. return height_;
  97. }
  98.  
  99. std::size_t width() const {
  100. return width_;
  101. }
  102.  
  103. std::size_t size() const {
  104. return height() * width();
  105. }
  106.  
  107. T * data() {
  108. return data_.get();
  109. }
  110. T const* data() const {
  111. return data_.get();
  112. }
  113.  
  114.  
  115. private:
  116. std::unique_ptr<T[]> data_;
  117. std::size_t height_;
  118. std::size_t width_;
  119. };
  120.  
  121.  
  122. int main() {
  123. matrix<int> m(3, 4);
  124.  
  125. for (std::size_t i = 0; i != m.size(); ++i) {
  126. m[i] = static_cast<int>(i);
  127. }
  128.  
  129. for (std::size_t i = 0; i != m.size(); ++i) {
  130. std::cout << m[i] << ' ';
  131. }
  132. std::cout << std::endl;
  133.  
  134. for (std::size_t i = 0; i != m.height(); ++i) {
  135. for (std::size_t j = 0; j != m.width(); ++j) {
  136. std::cout << m[i][j] << ' ';
  137. }
  138. std::cout << std::endl;
  139. }
  140. }
Success #stdin #stdout 0s 3472KB
stdin
Standard input is empty
stdout
0 1 2 3 4 5 6 7 8 9 10 11 
0 1 2 3 
4 5 6 7 
8 9 10 11