VCCC  2024.05
VisualCamp Common C++ library
matrix.hpp
Go to the documentation of this file.
1 # /*
2 # * Created by YongGyu Lee on 2020/02/04.
3 # */
4 #
5 # ifndef VCCC_MATH_MATRIX_MATRIX_HPP
6 # define VCCC_MATH_MATRIX_MATRIX_HPP
7 #
8 # include <cstddef>
9 # include <tuple>
10 # include <utility>
11 #
13 
14 namespace vccc {
15 
16 namespace internal {
17 namespace math {
18 
19 template<typename T, int m, int n>
20 struct traits<Matrix<T, m, n>> {
21  enum : int {
22  rows = m,
23  cols = n,
24  size = rows * cols,
25  };
26 
27  enum : int {
28  option = static_cast<int>(Flag::kDefault)
29  };
30  using value_type = T;
31 };
32 
33 struct matrix_ctor_all_t {};
34 struct matrix_ctor_diag_t {};
35 struct matrix_ctor_indexable_t {};
36 
37 constexpr matrix_ctor_all_t matrix_ctor_all;
38 constexpr matrix_ctor_diag_t matrix_ctor_diag;
39 constexpr matrix_ctor_indexable_t matrix_ctor_indexable;
40 
41 } // namespace math
42 } // namespace internal
43 
46 
56 template<typename T, int m, int n>
57 class Matrix : public MatrixBase<Matrix<T, m, n>> {
58  public:
59  using value_type = T;
63  using base_type::rows;
64  using base_type::cols;
65  using base_type::size;
66  using base_type::shortdim;
67 
68  template<typename U, int p, int q>
69  friend class Matrix;
70 
74  constexpr Matrix();
75 
76  constexpr explicit Matrix(T v0);
77  constexpr Matrix(T v0, T v1);
78  constexpr Matrix(T v0, T v1, T v2);
79  constexpr Matrix(T v0, T v1, T v2, T v3);
80  constexpr Matrix(T v0, T v1, T v2, T v3, T v4);
81  constexpr Matrix(T v0, T v1, T v2, T v3, T v4, T v5);
82  constexpr Matrix(T v0, T v1, T v2, T v3, T v4, T v5, T v6);
83  constexpr Matrix(T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7);
84  constexpr Matrix(T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7, T v8);
85  constexpr Matrix(T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7, T v8, T v9);
86  constexpr Matrix(T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7, T v8, T v9, T v10);
87  constexpr Matrix(T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7, T v8, T v9, T v10, T v11);
88  constexpr Matrix(T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7, T v8, T v9, T v10, T v11, T v12);
89  constexpr Matrix(T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7, T v8, T v9, T v10, T v11, T v12, T v13);
90  constexpr Matrix(T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7, T v8, T v9, T v10, T v11, T v12, T v13, T v14);
91  constexpr Matrix(T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7, T v8, T v9, T v10, T v11, T v12, T v13, T v14, T v15);
92 
105  template<std::size_t N, std::enable_if_t<(N <= m * n), int> = 0>
106  constexpr explicit Matrix(const T(& arr)[N])
107  : Matrix(internal::math::matrix_ctor_indexable, arr, std::make_index_sequence<N>{}, std::true_type{}) {}
108 
115  template<typename E, std::enable_if_t<
116  internal::math::is_same_size<matrix_type, E>::value &&
117  internal::math::is_same_type<matrix_type, E>::value, int> = 0>
118  constexpr Matrix(const MatrixBase<E>& expr)
119  : Matrix(internal::math::matrix_ctor_indexable, expr, std::make_index_sequence<size>{}, internal::math::is_alias_safe_t<E>{}) {}
120 
128  template<typename E, std::enable_if_t<
131  constexpr Matrix& operator=(const MatrixBase<E>& expr) {
132  Assign(expr, internal::math::is_alias_safe<E>{});
133  return *this;
134  }
135 
143  constexpr Matrix<U, m, n> AsType() const {
144  return Matrix<U, m, n>(internal::math::matrix_ctor_indexable, *this, std::make_index_sequence<m*n>{}, std::true_type{});
145  }
146 
154  template<int rows, int cols = (m * n) / rows, std::enable_if_t<m * n == rows * cols, int> = 0>
155  constexpr Matrix<T, rows, cols> Reshape() const {
156  return Matrix<T, rows, cols>(internal::math::matrix_ctor_indexable, *this, std::make_index_sequence<m*n>{}, std::true_type{});
157  }
158 
159 // inline MatrixProxyNocopy<matrix_type> noAlias() {
160 // return MatrixProxyNocopy<matrix_type>(*this);
161 // }
162 
166  constexpr static Matrix all(T value) {
167  return Matrix(internal::math::matrix_ctor_all, value, std::make_index_sequence<size>{});
168  }
169 
173  constexpr static Matrix zeros() {
174  return all(T(0));
175  }
176 
180  constexpr static Matrix ones() {
181  return all(T(1));
182  }
183 
187  constexpr static Matrix diag(const diag_type& value) {
188  return Matrix(internal::math::matrix_ctor_diag, value);
189  }
190 
194  template<typename Dummy = void, std::enable_if_t<
196  (n == m), int> = 0>
197  constexpr static Matrix eye() {
198  return Matrix(internal::math::matrix_ctor_all, internal::math::matrix_ctor_diag, 1);
199  }
200 
208  constexpr value_type& operator[](std::size_t i) noexcept { return data[i]; }
209  constexpr const value_type& operator[](std::size_t i) const noexcept { return data[i]; }
210 
219  constexpr value_type& operator()(std::size_t i) noexcept { return data[i]; }
220  constexpr const value_type& operator()(std::size_t i) const noexcept { return data[i]; }
221 
230  constexpr value_type& operator()(std::size_t i, std::size_t j) noexcept { return data[i * matrix_type::cols + j]; }
231  constexpr const value_type& operator()(std::size_t i, std::size_t j) const noexcept { return data[i * matrix_type::cols + j]; }
232 
233  private:
234  template<typename U, std::size_t... I>
235  constexpr Matrix(internal::math::matrix_ctor_indexable_t, const U& v, std::index_sequence<I...>, std::true_type)
236  : data{((void)I, static_cast<value_type>(v[I]))...} {}
237 
238  // TODO: Optimize
239  template<typename U, std::size_t... I>
240  constexpr Matrix(internal::math::matrix_ctor_indexable_t, const U& v, std::index_sequence<I...>, std::false_type)
241  : data{} {
242  auto copy = this->derived();
243  for(int i=0; i<std::index_sequence<I...>::size(); ++i)
244  copy[i] = v[i];
245  for(int i=0; i<std::index_sequence<I...>::size(); ++i)
246  (*this)[i] = std::move(copy[i]);
247  }
248 
249  template<std::size_t... I>
250  constexpr Matrix(internal::math::matrix_ctor_all_t, const T& value, std::index_sequence<I...>)
251  : data{((void)I, value)...} {}
252 
253  constexpr Matrix(internal::math::matrix_ctor_diag_t, const diag_type& value) : data{} {
254  for (int i = 0; i < shortdim; ++i)
255  data[i * cols + i] = value[i];
256  }
257 
258  constexpr Matrix(internal::math::matrix_ctor_all_t, internal::math::matrix_ctor_diag_t, const T& value) : data{} {
259  for (int i = 0; i < shortdim; ++i)
260  data[i * cols + i] = value;
261  }
262 
263  template<typename E>
264  constexpr void Assign(const MatrixBase<E>& expr, std::true_type) {
265  for(int i=0; i<size; ++i)
266  (*this)[i] = expr[i];
267  }
268 
269  // TODO: Optimize
270  template<typename E>
271  constexpr void Assign(const MatrixBase<E>& expr, std::false_type) {
272  auto copy = this->derived();
273  for(int i=0; i<matrix_type::size; ++i)
274  copy[i] = expr[i];
275  for(int i=0; i<matrix_type::size; ++i)
276  (*this)[i] = std::move(copy[i]);
277  }
278 
279  T data[m * n];
280 };
281 
283 using Matrix12i = Matrix<int, 1, 2>;
284 using Matrix13i = Matrix<int, 1, 3>;
285 using Matrix14i = Matrix<int, 1, 4>;
286 using Matrix21i = Matrix<int, 2, 1>;
287 using Matrix22i = Matrix<int, 2, 2>;
288 using Matrix23i = Matrix<int, 2, 3>;
289 using Matrix24i = Matrix<int, 2, 4>;
290 using Matrix31i = Matrix<int, 3, 1>;
291 using Matrix32i = Matrix<int, 3, 2>;
292 using Matrix33i = Matrix<int, 3, 3>;
293 using Matrix34i = Matrix<int, 3, 4>;
294 using Matrix41i = Matrix<int, 4, 1>;
295 using Matrix42i = Matrix<int, 4, 2>;
296 using Matrix43i = Matrix<int, 4, 3>;
297 using Matrix44i = Matrix<int, 4, 4>;
298 
299 using Matrix12f = Matrix<float, 1, 2>;
300 using Matrix13f = Matrix<float, 1, 3>;
301 using Matrix14f = Matrix<float, 1, 4>;
302 using Matrix21f = Matrix<float, 2, 1>;
303 using Matrix22f = Matrix<float, 2, 2>;
304 using Matrix23f = Matrix<float, 2, 3>;
305 using Matrix24f = Matrix<float, 2, 4>;
306 using Matrix31f = Matrix<float, 3, 1>;
307 using Matrix32f = Matrix<float, 3, 2>;
308 using Matrix33f = Matrix<float, 3, 3>;
309 using Matrix34f = Matrix<float, 3, 4>;
310 using Matrix41f = Matrix<float, 4, 1>;
311 using Matrix42f = Matrix<float, 4, 2>;
312 using Matrix43f = Matrix<float, 4, 3>;
313 using Matrix44f = Matrix<float, 4, 4>;
314 
315 using Matrix12d = Matrix<double, 1, 2>;
316 using Matrix13d = Matrix<double, 1, 3>;
317 using Matrix14d = Matrix<double, 1, 4>;
318 using Matrix21d = Matrix<double, 2, 1>;
319 using Matrix22d = Matrix<double, 2, 2>;
320 using Matrix23d = Matrix<double, 2, 3>;
321 using Matrix24d = Matrix<double, 2, 4>;
322 using Matrix31d = Matrix<double, 3, 1>;
323 using Matrix32d = Matrix<double, 3, 2>;
324 using Matrix33d = Matrix<double, 3, 3>;
325 using Matrix34d = Matrix<double, 3, 4>;
326 using Matrix41d = Matrix<double, 4, 1>;
327 using Matrix42d = Matrix<double, 4, 2>;
328 using Matrix43d = Matrix<double, 4, 3>;
329 using Matrix44d = Matrix<double, 4, 4>;
330 
331 template<typename T, int m, int n>
332 constexpr Matrix<T, m, n>::Matrix() : data{} {}
333 template<typename T, int m, int n>
334 constexpr Matrix<T, m, n>::Matrix(
335  T v0)
336  : data{std::move(v0)} {}
337 template<typename T, int m, int n>
338 constexpr Matrix<T, m, n>::Matrix(
339  T v0, T v1)
340  : data{std::move(v0), std::move(v1)} {}
341 template<typename T, int m, int n>
342 constexpr Matrix<T, m, n>::Matrix(
343  T v0, T v1, T v2)
344  : data{std::move(v0), std::move(v1), std::move(v2)} {}
345 template<typename T, int m, int n>
346 constexpr Matrix<T, m, n>::Matrix(
347  T v0, T v1, T v2, T v3)
348  : data{std::move(v0), std::move(v1), std::move(v2), std::move(v3)} {}
349 template<typename T, int m, int n>
350 constexpr Matrix<T, m, n>::Matrix(
351  T v0, T v1, T v2, T v3,
352  T v4)
353  : data{std::move(v0), std::move(v1), std::move(v2), std::move(v3),
354  std::move(v4)} {}
355 template<typename T, int m, int n>
356 constexpr Matrix<T, m, n>::Matrix(
357  T v0, T v1, T v2, T v3,
358  T v4, T v5)
359  : data{std::move(v0), std::move(v1), std::move(v2), std::move(v3),
360  std::move(v4), std::move(v5)} {}
361 template<typename T, int m, int n>
362 constexpr Matrix<T, m, n>::Matrix(
363  T v0, T v1, T v2, T v3,
364  T v4, T v5, T v6)
365  : data{std::move(v0), std::move(v1), std::move(v2), std::move(v3),
366  std::move(v4), std::move(v5), std::move(v6)} {}
367 template<typename T, int m, int n>
368 constexpr Matrix<T, m, n>::Matrix(
369  T v0, T v1, T v2, T v3,
370  T v4, T v5, T v6, T v7)
371  : data{std::move(v0), std::move(v1), std::move(v2), std::move(v3),
372  std::move(v4), std::move(v5), std::move(v6), std::move(v7)} {}
373 template<typename T, int m, int n>
374 constexpr Matrix<T, m, n>::Matrix(
375  T v0, T v1, T v2, T v3,
376  T v4, T v5, T v6, T v7,
377  T v8)
378  : data{std::move(v0), std::move(v1), std::move(v2), std::move(v3),
379  std::move(v4), std::move(v5), std::move(v6), std::move(v7),
380  std::move(v8)} {}
381 template<typename T, int m, int n>
382 constexpr Matrix<T, m, n>::Matrix(
383  T v0, T v1, T v2, T v3,
384  T v4, T v5, T v6, T v7,
385  T v8, T v9)
386  : data{std::move(v0), std::move(v1), std::move(v2), std::move(v3),
387  std::move(v4), std::move(v5), std::move(v6), std::move(v7),
388  std::move(v8), std::move(v9)} {}
389 template<typename T, int m, int n>
390 constexpr Matrix<T, m, n>::Matrix(
391  T v0, T v1, T v2, T v3,
392  T v4, T v5, T v6, T v7,
393  T v8, T v9, T v10)
394  : data{std::move(v0), std::move(v1), std::move(v2), std::move(v3),
395  std::move(v4), std::move(v5), std::move(v6), std::move(v7),
396  std::move(v8), std::move(v9), std::move(v10)} {}
397 template<typename T, int m, int n>
398 constexpr Matrix<T, m, n>::Matrix(
399  T v0, T v1, T v2, T v3,
400  T v4, T v5, T v6, T v7,
401  T v8, T v9, T v10, T v11)
402  : data{std::move(v0), std::move(v1), std::move(v2), std::move(v3),
403  std::move(v4), std::move(v5), std::move(v6), std::move(v7),
404  std::move(v8), std::move(v9), std::move(v10), std::move(v11)} {}
405 
406 template<typename T, int m, int n>
407 constexpr Matrix<T, m, n>::Matrix(
408  T v0, T v1, T v2, T v3,
409  T v4, T v5, T v6, T v7,
410  T v8, T v9, T v10, T v11,
411  T v12)
412  : data{std::move(v0), std::move(v1), std::move(v2), std::move(v3),
413  std::move(v4), std::move(v5), std::move(v6), std::move(v7),
414  std::move(v8), std::move(v9), std::move(v10), std::move(v11),
415  std::move(v12)} {}
416 template<typename T, int m, int n>
417 constexpr Matrix<T, m, n>::Matrix(
418  T v0, T v1, T v2, T v3,
419  T v4, T v5, T v6, T v7,
420  T v8, T v9, T v10, T v11,
421  T v12, T v13)
422  : data{std::move(v0), std::move(v1), std::move(v2), std::move(v3),
423  std::move(v4), std::move(v5), std::move(v6), std::move(v7),
424  std::move(v8), std::move(v9), std::move(v10), std::move(v11),
425  std::move(v12), std::move(v13)} {}
426 template<typename T, int m, int n>
427 constexpr Matrix<T, m, n>::Matrix(
428  T v0, T v1, T v2, T v3,
429  T v4, T v5, T v6, T v7,
430  T v8, T v9, T v10, T v11,
431  T v12, T v13, T v14)
432  : data{std::move(v0), std::move(v1), std::move(v2), std::move(v3),
433  std::move(v4), std::move(v5), std::move(v6), std::move(v7),
434  std::move(v8), std::move(v9), std::move(v10), std::move(v11),
435  std::move(v12), std::move(v13), std::move(v14)} {}
436 template<typename T, int m, int n>
437 constexpr Matrix<T, m, n>::Matrix(
438  T v0, T v1, T v2, T v3,
439  T v4, T v5, T v6, T v7,
440  T v8, T v9, T v10, T v11,
441  T v12, T v13, T v14, T v15)
442  : data{std::move(v0), std::move(v1), std::move(v2), std::move(v3),
443  std::move(v4), std::move(v5), std::move(v6), std::move(v7),
444  std::move(v8), std::move(v9), std::move(v10), std::move(v11),
445  std::move(v12), std::move(v13), std::move(v14), std::move(v15)} {}
446 
448 
449 // matrix out-of-class operations
450 
451 template<typename T, int m, int n>
452 static inline
453 Matrix<T, m, n>&
454 operator *= (Matrix<T, m, n>& mat, T val) {
455  for(int i=0; i<mat.size; ++i)
456  mat[i] *= val;
457  return mat;
458 }
459 
460 template<typename T, int m, int n>
461 static inline
462 Matrix<T, m, n>&
463 operator /= (Matrix<T, m, n>& mat, T val) {
464  for(int i=0; i<mat.size; ++i)
465  mat[i] /= val;
466  return mat;
467 }
468 
469 template<typename E, typename T, int m, int n>
470 static inline
471 Matrix<T, m, n>&
472 operator += (Matrix<T, m, n>& mat, const MatrixBase<E>& expr) {
473  for(int i=0; i<mat.size; ++i)
474  mat[i] += expr[i];
475  return mat;
476 }
477 
478 template<typename E, typename T, int m, int n>
479 static inline
480 Matrix<T, m, n>&
481 operator -= (Matrix<T, m, n>& mat, const MatrixBase<E>& expr) {
482  for(int i=0; i<mat.size; ++i)
483  mat[i] -= expr[i];
484  return mat;
485 }
486 
488 
489 } // namespace vccc
490 
491 template<typename T, int m, int n>
492 struct std::tuple_size<vccc::Matrix<T, m, n>>
493  : std::integral_constant<std::size_t, m * n> {};
494 
495 namespace std {
496 
497 template<std::size_t I, typename T, int m, int n>
498 constexpr inline std::enable_if_t<(I < m * n), typename vccc::Matrix<T, m, n>::value_type&>
500  return matrix[I];
501 }
502 
503 template<std::size_t I, typename T, int m, int n>
504 constexpr inline std::enable_if_t<(I < m * n), const typename vccc::Matrix<T, m, n>::value_type&>
505 get(const vccc::Matrix<T, m, n>& matrix) {
506  return matrix[I];
507 }
508 
509 template<std::size_t I, typename T, int m, int n>
510 constexpr inline std::enable_if_t<(I < m * n), typename vccc::Matrix<T, m, n>::value_type&&>
512  return std::move(matrix[I]);
513 }
514 
515 template<std::size_t I, typename T, int m, int n>
516 constexpr inline std::enable_if_t<(I < m * n), const typename vccc::Matrix<T, m, n>::value_type&&>
517 get(const vccc::Matrix<T, m, n>&& matrix) {
518  return std::move(matrix[I]);
519 }
520 
521 } // namespace std
522 
523 # endif // VCCC_MATH_MATRIX_MATRIX_HPP
Definition: matrix_base.hpp:20
constexpr const derived_type & derived() const
Definition: matrix_base.hpp:46
@ size
Definition: matrix_base.hpp:29
@ cols
Definition: matrix_base.hpp:28
@ rows
Definition: matrix_base.hpp:27
A class that represents 2D matrix.
Definition: matrix.hpp:57
constexpr Matrix(T v0, T v1, T v2, T v3, T v4)
@ size
Definition: matrix_base.hpp:29
constexpr Matrix(T v0, T v1, T v2, T v3, T v4, T v5)
Matrix< T, Matrix::shortdim, 1 > diag_type
Definition: matrix.hpp:62
constexpr Matrix(T v0, T v1, T v2, T v3, T v4, T v5, T v6)
constexpr Matrix(T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7, T v8, T v9, T v10, T v11, T v12, T v13, T v14)
constexpr Matrix(T v0, T v1)
constexpr Matrix< T, rows, cols > Reshape() const
Create a matrix with a different shape but same size.
Definition: matrix.hpp:155
constexpr const value_type & operator()(std::size_t i, std::size_t j) const noexcept
Definition: matrix.hpp:231
constexpr Matrix(T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7, T v8, T v9)
constexpr Matrix(T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7, T v8, T v9, T v10, T v11)
constexpr Matrix()
Create a zero matrix.
constexpr value_type & operator()(std::size_t i, std::size_t j) noexcept
Access element at (i, j) The behavior is undefined if i * j > size
Definition: matrix.hpp:230
constexpr value_type & operator()(std::size_t i) noexcept
Access element ith element from the beginning as if the Matrix is 1-D The behavior is undefined if i ...
Definition: matrix.hpp:219
constexpr Matrix(T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7, T v8, T v9, T v10)
constexpr Matrix(const MatrixBase< E > &expr)
Construct from matrix expression.
Definition: matrix.hpp:118
@ cols
Definition: matrix_base.hpp:28
constexpr Matrix(T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7, T v8, T v9, T v10, T v11, T v12)
constexpr Matrix(T v0, T v1, T v2, T v3)
constexpr Matrix(T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7, T v8, T v9, T v10, T v11, T v12, T v13)
@ rows
Definition: matrix_base.hpp:27
constexpr Matrix(T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7)
constexpr static Matrix diag(const diag_type &value)
Create a diagonal matrix.
Definition: matrix.hpp:187
constexpr const value_type & operator[](std::size_t i) const noexcept
Definition: matrix.hpp:209
constexpr Matrix(T v0, T v1, T v2)
constexpr Matrix< U, m, n > AsType() const
Create a matrix with a different type.
Definition: matrix.hpp:143
constexpr static Matrix zeros()
Create zero matrix.
Definition: matrix.hpp:173
constexpr static Matrix all(T value)
Create all-value matrix.
Definition: matrix.hpp:166
constexpr const value_type & operator()(std::size_t i) const noexcept
Definition: matrix.hpp:220
constexpr Matrix(T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7, T v8)
constexpr Matrix(T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7, T v8, T v9, T v10, T v11, T v12, T v13, T v14, T v15)
constexpr Matrix & operator=(const MatrixBase< E > &expr)
Assign from matrix expression.
Definition: matrix.hpp:131
constexpr static Matrix eye()
Create an identity matrix.
Definition: matrix.hpp:197
friend class Matrix
Definition: matrix.hpp:69
constexpr Matrix(T v0)
constexpr static Matrix ones()
Create all-ones matrix.
Definition: matrix.hpp:180
constexpr value_type & operator[](std::size_t i) noexcept
Access element ith element from the beginning as if the Matrix is 1-D The behavior is undefined if i ...
Definition: matrix.hpp:208
T value_type
Definition: matrix.hpp:59
constexpr VCCC_INLINE_OR_STATIC detail::copy_niebloid copy
Definition: copy.hpp:69
constexpr VCCC_INLINE_OR_STATIC detail::data_niebloid data
obtains a pointer to the beginning of a contiguous range
Definition: data.hpp:103
constexpr VCCC_INLINE_OR_STATIC detail::size_niebloid size
returns the size of a container or array
Definition: size.hpp:145
Definition: matrix.hpp:495
constexpr std::enable_if_t<(I< m *n), typename vccc::Matrix< T, m, n >::value_type & > get(vccc::Matrix< T, m, n > &matrix)
Definition: matrix.hpp:499
Definition: directory.h:12
constexpr auto size(const C &c) -> decltype(c.size())
Definition: size.hpp:16
constexpr VCCC_INLINE_OR_STATIC detail::element_niebloid< 1 > value
Definition: key_value.hpp:35