tuples.hpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. // Boost.Geometry Index
  2. //
  3. // Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
  4. //
  5. // This file was modified by Oracle on 2019, 2020.
  6. // Modifications copyright (c) 2019-2020 Oracle and/or its affiliates.
  7. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  8. //
  9. // Use, modification and distribution is subject to the Boost Software License,
  10. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  11. // http://www.boost.org/LICENSE_1_0.txt)
  12. #ifndef BOOST_GEOMETRY_UTIL_TUPLES_HPP
  13. #define BOOST_GEOMETRY_UTIL_TUPLES_HPP
  14. #include <boost/geometry/core/config.hpp>
  15. #include <boost/mpl/if.hpp>
  16. #include <boost/mpl/not.hpp>
  17. #include <boost/tuple/tuple.hpp>
  18. #include <boost/type_traits/integral_constant.hpp>
  19. #include <boost/type_traits/is_same.hpp>
  20. #include <utility>
  21. #ifdef BOOST_GEOMETRY_CXX11_TUPLE
  22. #include <tuple>
  23. #endif // BOOST_GEOMETRY_CXX11_TUPLE
  24. namespace boost { namespace geometry { namespace tuples {
  25. using boost::tuples::null_type;
  26. template <int I, typename Tuple>
  27. struct element
  28. : boost::tuples::element<I, Tuple>
  29. {};
  30. template <typename Tuple>
  31. struct size
  32. : boost::tuples::length<Tuple>
  33. {};
  34. template <int I, typename HT, typename TT>
  35. inline typename boost::tuples::access_traits
  36. <
  37. typename boost::tuples::element<I, boost::tuples::cons<HT, TT> >::type
  38. >::non_const_type
  39. get(boost::tuples::cons<HT, TT> & tup)
  40. {
  41. return boost::tuples::get<I>(tup);
  42. }
  43. template <int I, typename HT, typename TT>
  44. inline typename boost::tuples::access_traits
  45. <
  46. typename boost::tuples::element<I, boost::tuples::cons<HT, TT> >::type
  47. >::const_type
  48. get(boost::tuples::cons<HT, TT> const& tup)
  49. {
  50. return boost::tuples::get<I>(tup);
  51. }
  52. template <int I, typename F, typename S>
  53. struct element<I, std::pair<F, S> >
  54. {};
  55. template <typename F, typename S>
  56. struct element<0, std::pair<F, S> >
  57. {
  58. typedef F type;
  59. };
  60. template <typename F, typename S>
  61. struct element<1, std::pair<F, S> >
  62. {
  63. typedef S type;
  64. };
  65. template <typename F, typename S>
  66. struct size<std::pair<F, S> >
  67. : boost::integral_constant<int, 2>
  68. {};
  69. template <int I, typename Pair>
  70. struct get_pair;
  71. template <typename F, typename S>
  72. struct get_pair<0, std::pair<F, S> >
  73. {
  74. typedef F type;
  75. static inline F& apply(std::pair<F, S> & p)
  76. {
  77. return p.first;
  78. }
  79. static inline F const& apply(std::pair<F, S> const& p)
  80. {
  81. return p.first;
  82. }
  83. };
  84. template <typename F, typename S>
  85. struct get_pair<1, std::pair<F, S> >
  86. {
  87. typedef S type;
  88. static inline S& apply(std::pair<F, S> & p)
  89. {
  90. return p.second;
  91. }
  92. static inline S const& apply(std::pair<F, S> const& p)
  93. {
  94. return p.second;
  95. }
  96. };
  97. template <int I, typename F, typename S>
  98. inline typename get_pair<I, std::pair<F, S> >::type&
  99. get(std::pair<F, S> & p)
  100. {
  101. return get_pair<I, std::pair<F, S> >::apply(p);
  102. }
  103. template <int I, typename F, typename S>
  104. inline typename get_pair<I, std::pair<F, S> >::type const&
  105. get(std::pair<F, S> const& p)
  106. {
  107. return get_pair<I, std::pair<F, S> >::apply(p);
  108. }
  109. #ifdef BOOST_GEOMETRY_CXX11_TUPLE
  110. template <int I, typename ...Ts>
  111. struct element<I, std::tuple<Ts...> >
  112. : std::tuple_element<I, std::tuple<Ts...> >
  113. {};
  114. template <typename ...Ts>
  115. struct size<std::tuple<Ts...> >
  116. : std::tuple_size<std::tuple<Ts...> >
  117. {};
  118. template <int I, typename ...Ts>
  119. inline typename std::tuple_element<I, std::tuple<Ts...> >::type&
  120. get(std::tuple<Ts...> & tup)
  121. {
  122. return std::get<I>(tup);
  123. }
  124. template <int I, typename ...Ts>
  125. inline typename std::tuple_element<I, std::tuple<Ts...> >::type const&
  126. get(std::tuple<Ts...> const& tup)
  127. {
  128. return std::get<I>(tup);
  129. }
  130. #endif // BOOST_GEOMETRY_CXX11_TUPLE
  131. // find_index_if
  132. // Searches for the index of an element for which UnaryPredicate returns true
  133. // If such element is not found the result is N
  134. template
  135. <
  136. typename Tuple,
  137. template <typename> class UnaryPred,
  138. int I = 0,
  139. int N = size<Tuple>::value
  140. >
  141. struct find_index_if
  142. : boost::mpl::if_c
  143. <
  144. UnaryPred<typename element<I, Tuple>::type>::value,
  145. boost::integral_constant<int, I>,
  146. typename find_index_if<Tuple, UnaryPred, I+1, N>::type
  147. >::type
  148. {};
  149. template
  150. <
  151. typename Tuple,
  152. template <typename> class UnaryPred,
  153. int N
  154. >
  155. struct find_index_if<Tuple, UnaryPred, N, N>
  156. : boost::integral_constant<int, N>
  157. {};
  158. // find_if
  159. // Searches for an element for which UnaryPredicate returns true
  160. // If such element is not found the result is boost::tuples::null_type
  161. template
  162. <
  163. typename Tuple,
  164. template <typename> class UnaryPred,
  165. int I = 0,
  166. int N = size<Tuple>::value
  167. >
  168. struct find_if
  169. : boost::mpl::if_c
  170. <
  171. UnaryPred<typename element<I, Tuple>::type>::value,
  172. element<I, Tuple>,
  173. find_if<Tuple, UnaryPred, I+1, N>
  174. >::type
  175. {};
  176. template
  177. <
  178. typename Tuple,
  179. template <typename> class UnaryPred,
  180. int N
  181. >
  182. struct find_if<Tuple, UnaryPred, N, N>
  183. {
  184. typedef boost::tuples::null_type type;
  185. };
  186. // is_found
  187. // Returns true if a type T (the result of find_if) was found.
  188. template <typename T>
  189. struct is_found
  190. : boost::mpl::not_<boost::is_same<T, boost::tuples::null_type> >
  191. {};
  192. // is_not_found
  193. // Returns true if a type T (the result of find_if) was not found.
  194. template <typename T>
  195. struct is_not_found
  196. : boost::is_same<T, boost::tuples::null_type>
  197. {};
  198. // exists_if
  199. // Returns true if search for element meeting UnaryPred can be found.
  200. template <typename Tuple, template <typename> class UnaryPred>
  201. struct exists_if
  202. : is_found<typename find_if<Tuple, UnaryPred>::type>
  203. {};
  204. // push_back
  205. // A utility used to create a type/object of a Tuple containing
  206. // all types/objects stored in another Tuple plus additional one.
  207. template <typename Tuple,
  208. typename T,
  209. size_t I = 0,
  210. size_t N = size<Tuple>::value>
  211. struct push_back_bt
  212. {
  213. typedef
  214. boost::tuples::cons<
  215. typename element<I, Tuple>::type,
  216. typename push_back_bt<Tuple, T, I+1, N>::type
  217. > type;
  218. static type apply(Tuple const& tup, T const& t)
  219. {
  220. return
  221. type(
  222. geometry::tuples::get<I>(tup),
  223. push_back_bt<Tuple, T, I+1, N>::apply(tup, t)
  224. );
  225. }
  226. };
  227. template <typename Tuple, typename T, size_t N>
  228. struct push_back_bt<Tuple, T, N, N>
  229. {
  230. typedef boost::tuples::cons<T, boost::tuples::null_type> type;
  231. static type apply(Tuple const&, T const& t)
  232. {
  233. return type(t, boost::tuples::null_type());
  234. }
  235. };
  236. template <typename Tuple, typename T>
  237. struct push_back
  238. : push_back_bt<Tuple, T>
  239. {};
  240. template <typename F, typename S, typename T>
  241. struct push_back<std::pair<F, S>, T>
  242. {
  243. #ifdef BOOST_GEOMETRY_CXX11_TUPLE
  244. typedef std::tuple<F, S, T> type;
  245. #else
  246. typedef boost::tuple<F, S, T> type;
  247. #endif // BOOST_GEOMETRY_CXX11_TUPLE
  248. static type apply(std::pair<F, S> const& p, T const& t)
  249. {
  250. return type(p.first, p.second, t);
  251. }
  252. #ifdef BOOST_GEOMETRY_CXX11_TUPLE
  253. #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  254. static type apply(std::pair<F, S> && p, T const& t)
  255. {
  256. return type(std::move(p.first), std::move(p.second), t);
  257. }
  258. static type apply(std::pair<F, S> && p, T && t)
  259. {
  260. return type(std::move(p.first), std::move(p.second), std::move(t));
  261. }
  262. #endif
  263. #endif // BOOST_GEOMETRY_CXX11_TUPLE
  264. };
  265. #ifdef BOOST_GEOMETRY_CXX11_TUPLE
  266. // NOTE: In C++14 std::integer_sequence and std::make_integer_sequence could be used
  267. template <int... Is>
  268. struct int_sequence {};
  269. template <int N, int ...Is>
  270. struct make_int_sequence
  271. {
  272. typedef typename make_int_sequence<N - 1, N - 1, Is...>::type type;
  273. };
  274. template <int ...Is>
  275. struct make_int_sequence<0, Is...>
  276. {
  277. typedef int_sequence<Is...> type;
  278. };
  279. template <typename Is, typename Tuple, typename T>
  280. struct push_back_st;
  281. template <int ...Is, typename ...Ts, typename T>
  282. struct push_back_st<int_sequence<Is...>, std::tuple<Ts...>, T>
  283. {
  284. typedef std::tuple<Ts..., T> type;
  285. static type apply(std::tuple<Ts...> const& tup, T const& t)
  286. {
  287. return type(std::get<Is>(tup)..., t);
  288. }
  289. #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  290. static type apply(std::tuple<Ts...> && tup, T const& t)
  291. {
  292. return type(std::move(std::get<Is>(tup))..., t);
  293. }
  294. static type apply(std::tuple<Ts...> && tup, T && t)
  295. {
  296. return type(std::move(std::get<Is>(tup))..., std::move(t));
  297. }
  298. #endif
  299. };
  300. template <typename ...Ts, typename T>
  301. struct push_back<std::tuple<Ts...>, T>
  302. : push_back_st
  303. <
  304. typename make_int_sequence<sizeof...(Ts)>::type,
  305. std::tuple<Ts...>,
  306. T
  307. >
  308. {};
  309. #endif // BOOST_GEOMETRY_CXX11_TUPLE
  310. }}} // namespace boost::geometry::tuples
  311. #endif // BOOST_GEOMETRY_UTIL_TUPLES_HPP