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
13 #ifndef BOOST_GEOMETRY_UTIL_TUPLES_HPP
14 #define BOOST_GEOMETRY_UTIL_TUPLES_HPP
15
16 #include <boost/geometry/core/config.hpp>
17
18 #include <boost/mpl/if.hpp>
19 #include <boost/mpl/not.hpp>
20 #include <boost/tuple/tuple.hpp>
21 #include <boost/type_traits/integral_constant.hpp>
22 #include <boost/type_traits/is_same.hpp>
23
24 #include <utility>
25
26 #ifdef BOOST_GEOMETRY_CXX11_TUPLE
27
28 #include <tuple>
29
30 #endif // BOOST_GEOMETRY_CXX11_TUPLE
31
32 namespace boost { namespace geometry { namespace tuples {
33
34
35 using boost::tuples::null_type;
36
37
38 template <int I, typename Tuple>
39 struct element
40 : boost::tuples::element<I, Tuple>
41 {};
42
43 template <typename Tuple>
44 struct size
45 : boost::tuples::length<Tuple>
46 {};
47
48 template <int I, typename HT, typename TT>
49 inline typename boost::tuples::access_traits
50 <
51 typename boost::tuples::element<I, boost::tuples::cons<HT, TT> >::type
52 >::non_const_type
get(boost::tuples::cons<HT,TT> & tup)53 get(boost::tuples::cons<HT, TT> & tup)
54 {
55 return boost::tuples::get<I>(tup);
56 }
57
58 template <int I, typename HT, typename TT>
59 inline typename boost::tuples::access_traits
60 <
61 typename boost::tuples::element<I, boost::tuples::cons<HT, TT> >::type
62 >::const_type
get(boost::tuples::cons<HT,TT> const & tup)63 get(boost::tuples::cons<HT, TT> const& tup)
64 {
65 return boost::tuples::get<I>(tup);
66 }
67
68
69 template <int I, typename F, typename S>
70 struct element<I, std::pair<F, S> >
71 {};
72
73 template <typename F, typename S>
74 struct element<0, std::pair<F, S> >
75 {
76 typedef F type;
77 };
78
79 template <typename F, typename S>
80 struct element<1, std::pair<F, S> >
81 {
82 typedef S type;
83 };
84
85 template <typename F, typename S>
86 struct size<std::pair<F, S> >
87 : boost::integral_constant<int, 2>
88 {};
89
90 template <int I, typename Pair>
91 struct get_pair;
92
93 template <typename F, typename S>
94 struct get_pair<0, std::pair<F, S> >
95 {
96 typedef F type;
97
applyboost::geometry::tuples::get_pair98 static inline F& apply(std::pair<F, S> & p)
99 {
100 return p.first;
101 }
102
applyboost::geometry::tuples::get_pair103 static inline F const& apply(std::pair<F, S> const& p)
104 {
105 return p.first;
106 }
107 };
108
109 template <typename F, typename S>
110 struct get_pair<1, std::pair<F, S> >
111 {
112 typedef S type;
113
applyboost::geometry::tuples::get_pair114 static inline S& apply(std::pair<F, S> & p)
115 {
116 return p.second;
117 }
118
applyboost::geometry::tuples::get_pair119 static inline S const& apply(std::pair<F, S> const& p)
120 {
121 return p.second;
122 }
123 };
124
125 template <int I, typename F, typename S>
126 inline typename get_pair<I, std::pair<F, S> >::type&
get(std::pair<F,S> & p)127 get(std::pair<F, S> & p)
128 {
129 return get_pair<I, std::pair<F, S> >::apply(p);
130 }
131
132 template <int I, typename F, typename S>
133 inline typename get_pair<I, std::pair<F, S> >::type const&
get(std::pair<F,S> const & p)134 get(std::pair<F, S> const& p)
135 {
136 return get_pair<I, std::pair<F, S> >::apply(p);
137 }
138
139 #ifdef BOOST_GEOMETRY_CXX11_TUPLE
140
141 template <int I, typename ...Ts>
142 struct element<I, std::tuple<Ts...> >
143 : std::tuple_element<I, std::tuple<Ts...> >
144 {};
145
146 template <typename ...Ts>
147 struct size<std::tuple<Ts...> >
148 : std::tuple_size<std::tuple<Ts...> >
149 {};
150
151 template <int I, typename ...Ts>
152 inline typename std::tuple_element<I, std::tuple<Ts...> >::type&
get(std::tuple<Ts...> & tup)153 get(std::tuple<Ts...> & tup)
154 {
155 return std::get<I>(tup);
156 }
157
158 template <int I, typename ...Ts>
159 inline typename std::tuple_element<I, std::tuple<Ts...> >::type const&
get(std::tuple<Ts...> const & tup)160 get(std::tuple<Ts...> const& tup)
161 {
162 return std::get<I>(tup);
163 }
164
165 #endif // BOOST_GEOMETRY_CXX11_TUPLE
166
167
168 // find_index_if
169 // Searches for the index of an element for which UnaryPredicate returns true
170 // If such element is not found the result is N
171
172 template
173 <
174 typename Tuple,
175 template <typename> class UnaryPred,
176 int I = 0,
177 int N = size<Tuple>::value
178 >
179 struct find_index_if
180 : boost::mpl::if_c
181 <
182 UnaryPred<typename element<I, Tuple>::type>::value,
183 boost::integral_constant<int, I>,
184 typename find_index_if<Tuple, UnaryPred, I+1, N>::type
185 >::type
186 {};
187
188 template
189 <
190 typename Tuple,
191 template <typename> class UnaryPred,
192 int N
193 >
194 struct find_index_if<Tuple, UnaryPred, N, N>
195 : boost::integral_constant<int, N>
196 {};
197
198
199 // find_if
200 // Searches for an element for which UnaryPredicate returns true
201 // If such element is not found the result is boost::tuples::null_type
202
203 template
204 <
205 typename Tuple,
206 template <typename> class UnaryPred,
207 int I = 0,
208 int N = size<Tuple>::value
209 >
210 struct find_if
211 : boost::mpl::if_c
212 <
213 UnaryPred<typename element<I, Tuple>::type>::value,
214 element<I, Tuple>,
215 find_if<Tuple, UnaryPred, I+1, N>
216 >::type
217 {};
218
219 template
220 <
221 typename Tuple,
222 template <typename> class UnaryPred,
223 int N
224 >
225 struct find_if<Tuple, UnaryPred, N, N>
226 {
227 typedef boost::tuples::null_type type;
228 };
229
230
231 // is_found
232 // Returns true if a type T (the result of find_if) was found.
233
234 template <typename T>
235 struct is_found
236 : boost::mpl::not_<boost::is_same<T, boost::tuples::null_type> >
237 {};
238
239
240 // is_not_found
241 // Returns true if a type T (the result of find_if) was not found.
242
243 template <typename T>
244 struct is_not_found
245 : boost::is_same<T, boost::tuples::null_type>
246 {};
247
248
249 // exists_if
250 // Returns true if search for element meeting UnaryPred can be found.
251
252 template <typename Tuple, template <typename> class UnaryPred>
253 struct exists_if
254 : is_found<typename find_if<Tuple, UnaryPred>::type>
255 {};
256
257
258 // push_back
259 // A utility used to create a type/object of a Tuple containing
260 // all types/objects stored in another Tuple plus additional one.
261
262 template <typename Tuple,
263 typename T,
264 size_t I = 0,
265 size_t N = size<Tuple>::value>
266 struct push_back_bt
267 {
268 typedef
269 boost::tuples::cons<
270 typename element<I, Tuple>::type,
271 typename push_back_bt<Tuple, T, I+1, N>::type
272 > type;
273
applyboost::geometry::tuples::push_back_bt274 static type apply(Tuple const& tup, T const& t)
275 {
276 return
277 type(
278 geometry::tuples::get<I>(tup),
279 push_back_bt<Tuple, T, I+1, N>::apply(tup, t)
280 );
281 }
282 };
283
284 template <typename Tuple, typename T, size_t N>
285 struct push_back_bt<Tuple, T, N, N>
286 {
287 typedef boost::tuples::cons<T, boost::tuples::null_type> type;
288
applyboost::geometry::tuples::push_back_bt289 static type apply(Tuple const&, T const& t)
290 {
291 return type(t, boost::tuples::null_type());
292 }
293 };
294
295 template <typename Tuple, typename T>
296 struct push_back
297 : push_back_bt<Tuple, T>
298 {};
299
300 template <typename F, typename S, typename T>
301 struct push_back<std::pair<F, S>, T>
302 {
303 #ifdef BOOST_GEOMETRY_CXX11_TUPLE
304 typedef std::tuple<F, S, T> type;
305 #else
306 typedef boost::tuple<F, S, T> type;
307 #endif // BOOST_GEOMETRY_CXX11_TUPLE
308
applyboost::geometry::tuples::push_back309 static type apply(std::pair<F, S> const& p, T const& t)
310 {
311 return type(p.first, p.second, t);
312 }
313
314 #ifdef BOOST_GEOMETRY_CXX11_TUPLE
315 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
316
applyboost::geometry::tuples::push_back317 static type apply(std::pair<F, S> && p, T const& t)
318 {
319 return type(std::move(p.first), std::move(p.second), t);
320 }
321
applyboost::geometry::tuples::push_back322 static type apply(std::pair<F, S> && p, T && t)
323 {
324 return type(std::move(p.first), std::move(p.second), std::move(t));
325 }
326
327 #endif
328 #endif // BOOST_GEOMETRY_CXX11_TUPLE
329
330 };
331
332 #ifdef BOOST_GEOMETRY_CXX11_TUPLE
333
334 // NOTE: In C++14 std::integer_sequence and std::make_integer_sequence could be used
335
336 template <int... Is>
337 struct int_sequence {};
338
339 template <int N, int ...Is>
340 struct make_int_sequence
341 {
342 typedef typename make_int_sequence<N - 1, N - 1, Is...>::type type;
343 };
344
345 template <int ...Is>
346 struct make_int_sequence<0, Is...>
347 {
348 typedef int_sequence<Is...> type;
349 };
350
351 template <typename Is, typename Tuple, typename T>
352 struct push_back_st;
353
354 template <int ...Is, typename ...Ts, typename T>
355 struct push_back_st<int_sequence<Is...>, std::tuple<Ts...>, T>
356 {
357 typedef std::tuple<Ts..., T> type;
358
applyboost::geometry::tuples::push_back_st359 static type apply(std::tuple<Ts...> const& tup, T const& t)
360 {
361 return type(std::get<Is>(tup)..., t);
362 }
363
364 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
365
applyboost::geometry::tuples::push_back_st366 static type apply(std::tuple<Ts...> && tup, T const& t)
367 {
368 return type(std::move(std::get<Is>(tup))..., t);
369 }
370
applyboost::geometry::tuples::push_back_st371 static type apply(std::tuple<Ts...> && tup, T && t)
372 {
373 return type(std::move(std::get<Is>(tup))..., std::move(t));
374 }
375
376 #endif
377 };
378
379 template <typename ...Ts, typename T>
380 struct push_back<std::tuple<Ts...>, T>
381 : push_back_st
382 <
383 typename make_int_sequence<sizeof...(Ts)>::type,
384 std::tuple<Ts...>,
385 T
386 >
387 {};
388
389 #endif // BOOST_GEOMETRY_CXX11_TUPLE
390
391
392 }}} // namespace boost::geometry::tuples
393
394 #endif // BOOST_GEOMETRY_UTIL_TUPLES_HPP
395