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