sequence.hpp 7.4 KB

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