sequence.hpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. // Boost.Geometry
  2. // Copyright (c) 2020-2021, 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. using type = typename sequence_element<I - 1, type_sequence<Ts...>>::type;
  42. };
  43. template <typename T, typename ...Ts>
  44. struct sequence_element<0, type_sequence<T, Ts...>>
  45. {
  46. using type = T;
  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 ...Ts>
  61. struct pack_front
  62. {
  63. static_assert(sizeof...(Ts) > 0, "Parameter pack can not be empty.");
  64. };
  65. template <typename T, typename ... Ts>
  66. struct pack_front<T, Ts...>
  67. {
  68. typedef T type;
  69. };
  70. template <typename Sequence>
  71. struct sequence_front
  72. : sequence_element<0, Sequence>
  73. {
  74. static_assert(sequence_size<Sequence>::value > 0, "Sequence can not be empty.");
  75. };
  76. template <typename Sequence>
  77. struct sequence_back
  78. : sequence_element<sequence_size<Sequence>::value - 1, Sequence>
  79. {
  80. static_assert(sequence_size<Sequence>::value > 0, "Sequence can not be empty.");
  81. };
  82. template <typename Sequence>
  83. struct sequence_empty
  84. : std::integral_constant
  85. <
  86. bool,
  87. sequence_size<Sequence>::value == 0
  88. >
  89. {};
  90. // Defines type member for the first type in sequence that satisfies UnaryPred.
  91. template
  92. <
  93. typename Sequence,
  94. template <typename> class UnaryPred
  95. >
  96. struct sequence_find_if {};
  97. template
  98. <
  99. typename T, typename ...Ts,
  100. template <typename> class UnaryPred
  101. >
  102. struct sequence_find_if<type_sequence<T, Ts...>, UnaryPred>
  103. : std::conditional
  104. <
  105. UnaryPred<T>::value,
  106. T,
  107. // TODO: prevent instantiation for the rest of the sequence if value is true
  108. typename sequence_find_if<type_sequence<Ts...>, UnaryPred>::type
  109. >
  110. {};
  111. template <template <typename> class UnaryPred>
  112. struct sequence_find_if<type_sequence<>, UnaryPred>
  113. {
  114. // TODO: This is technically incorrect because void can be stored in a type_sequence
  115. using type = void;
  116. };
  117. // sequence_merge<type_sequence<A, B>, type_sequence<C, D>>::type is
  118. // type_sequence<A, B, C, D>
  119. // sequence_merge<integer_sequence<A, B>, integer_sequence<C, D>>::type is
  120. // integer_sequence<A, B, C, D>
  121. template <typename ...Sequences>
  122. struct sequence_merge;
  123. template <typename S>
  124. struct sequence_merge<S>
  125. {
  126. using type = S;
  127. };
  128. template <typename ...T1s, typename ...T2s>
  129. struct sequence_merge<type_sequence<T1s...>, type_sequence<T2s...>>
  130. {
  131. using type = type_sequence<T1s..., T2s...>;
  132. };
  133. template <typename T, T ...I1s, T ...I2s>
  134. struct sequence_merge<std::integer_sequence<T, I1s...>, std::integer_sequence<T, I2s...>>
  135. {
  136. using type = std::integer_sequence<T, I1s..., I2s...>;
  137. };
  138. template <typename S1, typename S2, typename ...Sequences>
  139. struct sequence_merge<S1, S2, Sequences...>
  140. {
  141. using type = typename sequence_merge
  142. <
  143. typename sequence_merge<S1, S2>::type,
  144. typename sequence_merge<Sequences...>::type
  145. >::type;
  146. };
  147. // sequence_combine<type_sequence<A, B>, type_sequence<C, D>>::type is
  148. // type_sequence<type_sequence<A, C>, type_sequence<A, D>,
  149. // type_sequence<B, C>, type_sequence<B, D>>
  150. template <typename Sequence1, typename Sequence2>
  151. struct sequence_combine;
  152. template <typename ...T1s, typename ...T2s>
  153. struct sequence_combine<type_sequence<T1s...>, type_sequence<T2s...>>
  154. {
  155. template <typename T1>
  156. using type_sequence_t = type_sequence<type_sequence<T1, T2s>...>;
  157. using type = typename sequence_merge<type_sequence_t<T1s>...>::type;
  158. };
  159. // sequence_combine<integer_sequence<T, 1, 2>, integer_sequence<T, 3, 4>>::type is
  160. // type_sequence<integer_sequence<T, 1, 3>, integer_sequence<T, 1, 4>,
  161. // integer_sequence<T, 2, 3>, integer_sequence<T, 2, 4>>
  162. template <typename T, T ...I1s, T ...I2s>
  163. struct sequence_combine<std::integer_sequence<T, I1s...>, std::integer_sequence<T, I2s...>>
  164. {
  165. template <T I1>
  166. using type_sequence_t = type_sequence<std::integer_sequence<T, I1, I2s>...>;
  167. using type = typename sequence_merge<type_sequence_t<I1s>...>::type;
  168. };
  169. // Selects least element from a parameter pack based on
  170. // LessPred<T1, T2>::value comparison, similar to std::min_element
  171. template
  172. <
  173. template <typename, typename> class LessPred,
  174. typename ...Ts
  175. >
  176. struct pack_min_element;
  177. template
  178. <
  179. template <typename, typename> class LessPred,
  180. typename T
  181. >
  182. struct pack_min_element<LessPred, T>
  183. {
  184. using type = T;
  185. };
  186. template
  187. <
  188. template <typename, typename> class LessPred,
  189. typename T1, typename T2
  190. >
  191. struct pack_min_element<LessPred, T1, T2>
  192. {
  193. using type = std::conditional_t<LessPred<T1, T2>::value, T1, T2>;
  194. };
  195. template
  196. <
  197. template <typename, typename> class LessPred,
  198. typename T1, typename T2, typename ...Ts
  199. >
  200. struct pack_min_element<LessPred, T1, T2, Ts...>
  201. {
  202. using type = typename pack_min_element
  203. <
  204. LessPred,
  205. typename pack_min_element<LessPred, T1, T2>::type,
  206. typename pack_min_element<LessPred, Ts...>::type
  207. >::type;
  208. };
  209. // Selects least element from a sequence based on
  210. // LessPred<T1, T2>::value comparison, similar to std::min_element
  211. template
  212. <
  213. typename Sequence,
  214. template <typename, typename> class LessPred
  215. >
  216. struct sequence_min_element;
  217. template
  218. <
  219. typename ...Ts,
  220. template <typename, typename> class LessPred
  221. >
  222. struct sequence_min_element<type_sequence<Ts...>, LessPred>
  223. {
  224. using type = typename pack_min_element<LessPred, Ts...>::type;
  225. };
  226. // TODO: Since there are two kinds of parameter packs and sequences there probably should be two
  227. // versions of sequence_find_if as well as parameter_pack_min_element and sequence_min_element.
  228. // Currently these utilities support only types.
  229. } // namespace util
  230. }} // namespace boost::geometry
  231. #endif // BOOST_GEOMETRY_UTIL_SEQUENCE_HPP