Micro template library A library for building device drivers
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

114 lines
3.5 KiB

  1. /*!
  2. * \file pack.h
  3. * \brief Template meta-programming parameter pack container
  4. *
  5. * Copyright (C) 2018-2019 Christos Choutouridis
  6. *
  7. * This program is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU Lesser General Public License as
  9. * published by the Free Software Foundation, either version 3
  10. * of the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public License
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #ifndef __utl_meta_idx_sequence_h__
  21. #define __utl_meta_idx_sequence_h__
  22. #include <utl/core/impl.h>
  23. #include <utl/meta/integral.h>
  24. /*!
  25. * \ingroup meta
  26. * \defgroup index_sequence
  27. */
  28. //! @{
  29. namespace utl {
  30. namespace meta {
  31. /*!
  32. * Class template integer_sequence
  33. */
  34. template<typename _Tp, _Tp... _Idx>
  35. struct integer_sequence {
  36. using value_type = _Tp;
  37. static constexpr size_t size() noexcept {
  38. return sizeof...(_Idx);
  39. }
  40. };
  41. //! Alias template index_sequence
  42. template<index_t... _Idx>
  43. using index_sequence = integer_sequence<index_t, _Idx...>;
  44. //! make_integer_sequence
  45. //! @{
  46. namespace detail {
  47. // Stores a tuple of indices
  48. template<size_t... Idxs> struct index_tuple { };
  49. // Concatenates two index_tuples.
  50. template<typename It1, typename It2> struct it_cat_;
  51. template<size_t... It1, size_t... It2>
  52. struct it_cat_ <index_tuple<It1...>, index_tuple<It2...>> {
  53. using type = index_tuple<It1..., (It2 + sizeof...(It1))...>;
  54. };
  55. // Builds an index_tuple<0, 1, 2, ..., _Num-1>.
  56. template<size_t _Num>
  57. struct make_index_tuple_
  58. : it_cat_<eval<make_index_tuple_<_Num / 2>>,
  59. eval<make_index_tuple_<_Num - _Num / 2>>>
  60. { };
  61. // termination specialization for 1
  62. template<>
  63. struct make_index_tuple_<1> {
  64. using type = index_tuple<0>;
  65. };
  66. // termination specialization for 0
  67. template<>
  68. struct make_index_tuple_<0> {
  69. using type = index_tuple<>;
  70. };
  71. // factory type
  72. template<typename _Tp, _Tp _Num,
  73. typename _ISeq = eval<make_index_tuple_<_Num>>>
  74. struct make_integer_sequence_;
  75. template<typename _Tp, _Tp _Num, size_t... _Idx>
  76. struct make_integer_sequence_<_Tp, _Num, index_tuple<_Idx...>> {
  77. static_assert( _Num >= 0,
  78. "Cannot make integer sequence of negative length" );
  79. using type = integer_sequence<_Tp, static_cast<_Tp>(_Idx)...>;
  80. };
  81. }
  82. //! Alias template make_integer_sequence
  83. //! Complexity \f$ O(log N) \f$
  84. template<typename _Tp, _Tp N>
  85. using make_integer_sequence = eval<detail::make_integer_sequence_<_Tp, N>>;
  86. //! Alias template make_index_sequence
  87. //! Complexity \f$ O(log N) \f$
  88. template<index_t N>
  89. using make_index_sequence = make_integer_sequence<index_t, N>;
  90. //! Alias template index_sequence_for
  91. //! Complexity \f$ O(log N) \f$
  92. //! where N is sizeof...(_Ts)
  93. template<typename... _Ts>
  94. using index_sequence_for = make_index_sequence<sizeof...(_Ts)>;
  95. //! @}
  96. }}
  97. //! @}
  98. #endif /* __utl_meta_idx_sequence_h__ */