sequence.hpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. // Boost.Geometry
  2. // Copyright (c) 2020, Oracle and/or its affiliates.
  3. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  4. // Licensed under the Boost Software License version 1.0.
  5. // http://www.boost.org/users/license.html
  6. #ifndef BOOST_GEOMETRY_UTIL_SEQUENCE_HPP
  7. #define BOOST_GEOMETRY_UTIL_SEQUENCE_HPP
  8. #include <type_traits>
  9. namespace boost { namespace geometry
  10. {
  11. namespace util
  12. {
  13. // An alternative would be to use std:tuple and std::pair
  14. // but it would add dependency.
  15. template <typename ...Ts>
  16. struct type_sequence {};
  17. // true if T is a sequence
  18. template <typename T>
  19. struct is_sequence : std::false_type {};
  20. template <typename ...Ts>
  21. struct is_sequence<type_sequence<Ts...>> : std::true_type {};
  22. template <typename T, T ...Is>
  23. struct is_sequence<std::integer_sequence<T, Is...>> : std::true_type {};
  24. // number of elements in a sequence
  25. template <typename Sequence>
  26. struct sequence_size {};
  27. template <typename ...Ts>
  28. struct sequence_size<type_sequence<Ts...>>
  29. : std::integral_constant<std::size_t, sizeof...(Ts)>
  30. {};
  31. template <typename T, T ...Is>
  32. struct sequence_size<std::integer_sequence<T, Is...>>
  33. : std::integral_constant<std::size_t, sizeof...(Is)>
  34. {};
  35. // element of a sequence
  36. template <std::size_t I, typename Sequence>
  37. struct sequence_element {};
  38. template <std::size_t I, typename T, typename ...Ts>
  39. struct sequence_element<I, type_sequence<T, Ts...>>
  40. {
  41. typedef typename sequence_element<I - 1, type_sequence<Ts...>>::type type;
  42. };
  43. template <typename T, typename ...Ts>
  44. struct sequence_element<0, type_sequence<T, Ts...>>
  45. {
  46. typedef T type;
  47. };
  48. template <std::size_t I, typename T, T J, T ...Js>
  49. struct sequence_element<I, std::integer_sequence<T, J, Js...>>
  50. : std::integral_constant
  51. <
  52. T,
  53. sequence_element<I - 1, std::integer_sequence<T, Js...>>::value
  54. >
  55. {};
  56. template <typename T, T J, T ...Js>
  57. struct sequence_element<0, std::integer_sequence<T, J, Js...>>
  58. : std::integral_constant<T, J>
  59. {};
  60. template <typename Sequence>
  61. struct sequence_front
  62. : sequence_element<0, Sequence>
  63. {
  64. static_assert(sequence_size<Sequence>::value > 0, "Sequence can not be empty.");
  65. };
  66. template <typename Sequence>
  67. struct sequence_back
  68. : sequence_element<sequence_size<Sequence>::value - 1, Sequence>
  69. {
  70. static_assert(sequence_size<Sequence>::value > 0, "Sequence can not be empty.");
  71. };
  72. template <typename Sequence>
  73. struct sequence_empty
  74. : std::integral_constant
  75. <
  76. bool,
  77. sequence_size<Sequence>::value == 0
  78. >
  79. {};
  80. // merge<type_sequence<A, B>, type_sequence<C, D>>::type is
  81. // type_sequence<A, B, C, D>
  82. // merge<integer_sequence<A, B>, integer_sequence<C, D>>::type is
  83. // integer_sequence<A, B, C, D>
  84. template <typename ...Sequences>
  85. struct merge;
  86. template <typename S>
  87. struct merge<S>
  88. {
  89. typedef S type;
  90. };
  91. template <typename ...T1s, typename ...T2s>
  92. struct merge<type_sequence<T1s...>, type_sequence<T2s...>>
  93. {
  94. typedef type_sequence<T1s..., T2s...> type;
  95. };
  96. template <typename T, T ...I1s, T ...I2s>
  97. struct merge<std::integer_sequence<T, I1s...>, std::integer_sequence<T, I2s...>>
  98. {
  99. typedef std::integer_sequence<T, I1s..., I2s...> type;
  100. };
  101. template <typename S1, typename S2, typename ...Sequences>
  102. struct merge<S1, S2, Sequences...>
  103. {
  104. typedef typename merge
  105. <
  106. typename merge<S1, S2>::type,
  107. typename merge<Sequences...>::type
  108. >::type type;
  109. };
  110. // combine<type_sequence<A, B>, type_sequence<C, D>>::type is
  111. // type_sequence<type_sequence<A, C>, type_sequence<A, D>,
  112. // type_sequence<B, C>, type_sequence<B, D>>
  113. template <typename Sequence1, typename Sequence2>
  114. struct combine;
  115. template <typename ...T1s, typename ...T2s>
  116. struct combine<type_sequence<T1s...>, type_sequence<T2s...>>
  117. {
  118. template <typename U1, typename ...U2s>
  119. using type_sequence_t = type_sequence<type_sequence<U1, U2s>...>;
  120. typedef typename merge
  121. <
  122. type_sequence_t<T1s, T2s...>...
  123. >::type type;
  124. };
  125. // combine<integer_sequence<T, 1, 2>, integer_sequence<T, 3, 4>>::type is
  126. // type_sequence<integer_sequence<T, 1, 3>, integer_sequence<T, 1, 4>,
  127. // integer_sequence<T, 2, 3>, integer_sequence<T, 2, 4>>
  128. template <typename T, T ...I1s, T ...I2s>
  129. struct combine<std::integer_sequence<T, I1s...>, std::integer_sequence<T, I2s...>>
  130. {
  131. template <T J1, T ...J2s>
  132. using type_sequence_t = type_sequence<std::integer_sequence<T, J1, J2s>...>;
  133. typedef typename merge
  134. <
  135. type_sequence_t<I1s, I2s...>...
  136. >::type type;
  137. };
  138. // Selects least element from a parameter pack based on
  139. // LessPred<T1, T2>::value comparison, similar to std::min_element
  140. template
  141. <
  142. template <typename, typename> class LessPred,
  143. typename ...Ts
  144. >
  145. struct select_pack_element;
  146. template
  147. <
  148. template <typename, typename> class LessPred,
  149. typename T
  150. >
  151. struct select_pack_element<LessPred, T>
  152. {
  153. typedef T type;
  154. };
  155. template
  156. <
  157. template <typename, typename> class LessPred,
  158. typename T1, typename T2
  159. >
  160. struct select_pack_element<LessPred, T1, T2>
  161. {
  162. typedef std::conditional_t<LessPred<T1, T2>::value, T1, T2> type;
  163. };
  164. template
  165. <
  166. template <typename, typename> class LessPred,
  167. typename T1, typename T2, typename ...Ts
  168. >
  169. struct select_pack_element<LessPred, T1, T2, Ts...>
  170. {
  171. typedef typename select_pack_element
  172. <
  173. LessPred,
  174. typename select_pack_element<LessPred, T1, T2>::type,
  175. typename select_pack_element<LessPred, Ts...>::type
  176. >::type type;
  177. };
  178. // Selects least element from a sequence based on
  179. // LessPred<T1, T2>::value comparison, similar to std::min_element
  180. template
  181. <
  182. typename Sequence,
  183. template <typename, typename> class LessPred
  184. >
  185. struct select_element;
  186. template
  187. <
  188. typename ...Ts,
  189. template <typename, typename> class LessPred
  190. >
  191. struct select_element<type_sequence<Ts...>, LessPred>
  192. {
  193. typedef typename select_pack_element<LessPred, Ts...>::type type;
  194. };
  195. // Selects least pair sequence of elements from a parameter pack based on
  196. // LessPred<xxx_sequence<T11, T12>, xxx_sequence<T21, T22>>::value comparison
  197. template
  198. <
  199. typename Sequence1,
  200. typename Sequence2,
  201. template <typename, typename> class LessPred
  202. >
  203. struct select_combination_element
  204. {
  205. typedef typename select_element
  206. <
  207. typename combine<Sequence1, Sequence2>::type,
  208. LessPred
  209. >::type type;
  210. };
  211. } // namespace util
  212. }} // namespace boost::geometry
  213. #endif // BOOST_GEOMETRY_UTIL_SEQUENCE_HPP