fork download
  1. #include <array>
  2. #include <type_traits>
  3. #include <iostream>
  4. #include <iomanip>
  5.  
  6. // Get rid of any "Waah, you didn't use that!" warnings.
  7. // See http://stackoverflow.com/a/31654792/5386374
  8. #define UNUSED(x) [&x]{}()
  9.  
  10. // This example uses std::array for the actual array, since it's compile-time anyways.
  11. // This, in turn, lets it declare a lot of functions constexpr.
  12. // Const-correctness omitted for brevity. Remember to restore it for actual code.
  13. template<size_t Rows, size_t Cols>
  14. class Matrix {
  15. std::array<std::array<double, Cols>, Rows> mat;
  16.  
  17. public:
  18. // Default constructor. Clang _really_ likes braced initialiser lists.
  19. constexpr Matrix() : mat{{{{0}}}} {}
  20.  
  21. // Array constructor.
  22. constexpr Matrix(const decltype(mat)& arr) : mat(arr) {}
  23.  
  24. // -----
  25.  
  26. // Subscript operators.
  27.  
  28. // Generic operator. Matrix<x, y>, where x != 1 && y != 1.
  29. // Does what normal subscript operators do.
  30. template<bool R = (Rows == 1), bool C = (Cols == 1)>
  31. auto& operator[](std::enable_if_t<!R && !C, size_t> i) {
  32. return mat[i];
  33. }
  34.  
  35. // Magic operator. Matrix<1, x>, where x != 1.
  36. template<bool R = (Rows == 1), bool C = (Cols == 1)>
  37. auto& operator[](std::enable_if_t<(R && !C), size_t> i) {
  38. return mat[0][i];
  39. }
  40.  
  41. // Magic operator. Matrix<x, 1>, where x != 1.
  42. template<bool R = (Rows == 1), bool C = (Cols == 1)>
  43. auto& operator[](std::enable_if_t<C && !R, size_t> i) {
  44. return mat[i][0];
  45. }
  46.  
  47. // Scalar matrix operator. Matrix<1, 1>.
  48. // Just returns mat[0][0], for simplicity's sake. Might want to make it do something
  49. // more complex in your actual class.
  50. template<bool R = (Rows == 1), bool C = (Cols == 1)>
  51. auto& operator[](std::enable_if_t<R && C, size_t> i) {
  52. return mat[0][0];
  53. }
  54.  
  55. // -----
  56.  
  57. // A few interface helpers.
  58.  
  59. // Simple begin() & end(), for example's sake.
  60. // A better version would begin at mat[0][0] and end at mat[Rows - 1][Cols - 1].
  61. constexpr auto begin() const { return mat.begin(); }
  62. constexpr auto end() const { return mat.end(); }
  63.  
  64. // Generic helpers.
  65. constexpr size_t size() const { return mat.size() * mat[0].size(); }
  66. constexpr size_t rows() const { return mat.size(); }
  67. constexpr size_t cols() const { return mat[0].size(); }
  68.  
  69. // 1D Matrix helpers.
  70. constexpr bool is_one_d() const { return (Rows == 1) || (Cols == 1); }
  71. constexpr bool one_row() const { return Rows == 1; }
  72. constexpr size_t dimension() const { return (one_row() ? cols() : rows()); }
  73.  
  74. // -----
  75.  
  76. // Output.
  77. // Would need modification if better begin() & end() are implemented.
  78. friend std::ostream& operator<<(std::ostream& str, const Matrix<Rows, Cols>& m) {
  79. for (auto& row : m) {
  80. for (auto& elem : row) {
  81. str << std::setw(6) << elem << ' ';
  82. }
  83. str << '\n';
  84. }
  85. str << std::endl;
  86. return str;
  87. }
  88. };
  89.  
  90. // -----
  91.  
  92. // This should really use if constexpr, but online compilers don't really support it yet.
  93. template<size_t Rows, size_t Cols>
  94. void fill(Matrix<Rows, Cols>& m, std::enable_if_t<(Rows == 1) || (Cols == 1), int> dummy = 0) {
  95. UNUSED(dummy);
  96.  
  97. //for (size_t i = 0; i < (m.one_row() ? m.cols() : m.rows()); i++) {
  98. for (size_t i = 0; i < m.dimension(); i++) {
  99. m[i] = (i ? i : 0.5) * (i ? i : 0.5);
  100. }
  101. }
  102.  
  103. template<size_t Rows, size_t Cols>
  104. void fill(Matrix<Rows, Cols>& m, std::enable_if_t<!((Rows == 1) || (Cols == 1)), int> dummy = 0) {
  105. UNUSED(dummy);
  106.  
  107. for (size_t i = 0; i < m.rows(); i++) {
  108. for (size_t j = 0; j < m.cols(); j++) {
  109. m[i][j] = (i ? i : 0.5) * (j ? j : 0.5) + (i >= j ? 0.1 : -0.2);
  110. }
  111. }
  112. }
  113.  
  114. // -----
  115.  
  116. int main() {
  117. Matrix<3, 4> m34;
  118. fill(m34);
  119. m34[2][1] = 21.21;
  120. std::cout << m34;
  121.  
  122. // -----
  123.  
  124. Matrix<1, 4> m14;
  125. fill(m14);
  126. m14[3] = 03.03;
  127. std::cout << m14;
  128.  
  129. // -----
  130.  
  131. Matrix<3, 1> m31;
  132. fill(m31);
  133. m31[2] = 20.20;
  134. std::cout << m31;
  135.  
  136. std::array<std::array<double, 2>, 2> arr =
  137. { 8.8, -16.61, -8.8, 16.61 };
  138.  
  139. // -----
  140.  
  141. Matrix<2, 2> m22 = arr;
  142. std::cout << m22;
  143. }
Success #stdin #stdout 0s 3468KB
stdin
Standard input is empty
stdout
  0.35    0.3    0.8    1.3 
   0.6    1.1    1.8    2.8 
   1.1  21.21    4.1    5.8 

  0.25      1      4   3.03 

  0.25 
     1 
  20.2 

   8.8 -16.61 
  -8.8  16.61