3 // Copyright (c) 2020, Oracle and/or its affiliates.
5 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
7 // Licensed under the Boost Software License version 1.0.
8 // http://www.boost.org/users/license.html
10 #ifndef BOOST_GEOMETRY_UTIL_SEQUENCE_HPP
11 #define BOOST_GEOMETRY_UTIL_SEQUENCE_HPP
14 #include <type_traits>
17 namespace boost { namespace geometry
24 // An alternative would be to use std:tuple and std::pair
25 // but it would add dependency.
28 template <typename ...Ts>
29 struct type_sequence {};
32 // true if T is a sequence
34 struct is_sequence : std::false_type {};
36 template <typename ...Ts>
37 struct is_sequence<type_sequence<Ts...>> : std::true_type {};
39 template <typename T, T ...Is>
40 struct is_sequence<std::integer_sequence<T, Is...>> : std::true_type {};
43 // number of elements in a sequence
44 template <typename Sequence>
45 struct sequence_size {};
47 template <typename ...Ts>
48 struct sequence_size<type_sequence<Ts...>>
49 : std::integral_constant<std::size_t, sizeof...(Ts)>
52 template <typename T, T ...Is>
53 struct sequence_size<std::integer_sequence<T, Is...>>
54 : std::integral_constant<std::size_t, sizeof...(Is)>
58 // element of a sequence
59 template <std::size_t I, typename Sequence>
60 struct sequence_element {};
62 template <std::size_t I, typename T, typename ...Ts>
63 struct sequence_element<I, type_sequence<T, Ts...>>
65 typedef typename sequence_element<I - 1, type_sequence<Ts...>>::type type;
68 template <typename T, typename ...Ts>
69 struct sequence_element<0, type_sequence<T, Ts...>>
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
79 sequence_element<I - 1, std::integer_sequence<T, Js...>>::value
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>
89 template <typename Sequence>
91 : sequence_element<0, Sequence>
93 static_assert(sequence_size<Sequence>::value > 0, "Sequence can not be empty.");
97 template <typename Sequence>
99 : sequence_element<sequence_size<Sequence>::value - 1, Sequence>
101 static_assert(sequence_size<Sequence>::value > 0, "Sequence can not be empty.");
105 template <typename Sequence>
106 struct sequence_empty
107 : std::integral_constant
110 sequence_size<Sequence>::value == 0
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>
122 template <typename S>
128 template <typename ...T1s, typename ...T2s>
129 struct merge<type_sequence<T1s...>, type_sequence<T2s...>>
131 typedef type_sequence<T1s..., T2s...> type;
134 template <typename T, T ...I1s, T ...I2s>
135 struct merge<std::integer_sequence<T, I1s...>, std::integer_sequence<T, I2s...>>
137 typedef std::integer_sequence<T, I1s..., I2s...> type;
140 template <typename S1, typename S2, typename ...Sequences>
141 struct merge<S1, S2, Sequences...>
143 typedef typename merge
145 typename merge<S1, S2>::type,
146 typename merge<Sequences...>::type
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>
157 template <typename ...T1s, typename ...T2s>
158 struct combine<type_sequence<T1s...>, type_sequence<T2s...>>
160 template <typename U1, typename ...U2s>
161 using type_sequence_t = type_sequence<type_sequence<U1, U2s>...>;
163 typedef typename merge
165 type_sequence_t<T1s, T2s...>...
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...>>
175 template <T J1, T ...J2s>
176 using type_sequence_t = type_sequence<std::integer_sequence<T, J1, J2s>...>;
178 typedef typename merge
180 type_sequence_t<I1s, I2s...>...
185 // Selects least element from a parameter pack based on
186 // LessPred<T1, T2>::value comparison, similar to std::min_element
189 template <typename, typename> class LessPred,
192 struct select_pack_element;
196 template <typename, typename> class LessPred,
199 struct select_pack_element<LessPred, T>
206 template <typename, typename> class LessPred,
207 typename T1, typename T2
209 struct select_pack_element<LessPred, T1, T2>
211 typedef std::conditional_t<LessPred<T1, T2>::value, T1, T2> type;
216 template <typename, typename> class LessPred,
217 typename T1, typename T2, typename ...Ts
219 struct select_pack_element<LessPred, T1, T2, Ts...>
221 typedef typename select_pack_element
224 typename select_pack_element<LessPred, T1, T2>::type,
225 typename select_pack_element<LessPred, Ts...>::type
230 // Selects least element from a sequence based on
231 // LessPred<T1, T2>::value comparison, similar to std::min_element
235 template <typename, typename> class LessPred
237 struct select_element;
242 template <typename, typename> class LessPred
244 struct select_element<type_sequence<Ts...>, LessPred>
246 typedef typename select_pack_element<LessPred, Ts...>::type type;
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
256 template <typename, typename> class LessPred
258 struct select_combination_element
260 typedef typename select_element
262 typename combine<Sequence1, Sequence2>::type,
271 }} // namespace boost::geometry
274 #endif // BOOST_GEOMETRY_UTIL_SEQUENCE_HPP