Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:36:53

0001 // Boost.Geometry
0002 
0003 // Copyright (c) 2020-2023, Oracle and/or its affiliates.
0004 // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
0005 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
0006 
0007 // Licensed under the Boost Software License version 1.0.
0008 // http://www.boost.org/users/license.html
0009 
0010 #ifndef BOOST_GEOMETRY_UTIL_SEQUENCE_HPP
0011 #define BOOST_GEOMETRY_UTIL_SEQUENCE_HPP
0012 
0013 #include <utility>
0014 #include <type_traits>
0015 
0016 
0017 namespace boost { namespace geometry
0018 {
0019 
0020 namespace util
0021 {
0022 
0023 
0024 // An alternative would be to use std:tuple and std::pair
0025 //   but it would add dependency.
0026 
0027 
0028 template <typename ...Ts>
0029 struct type_sequence {};
0030 
0031 
0032 // true if T is a sequence
0033 template <typename T>
0034 struct is_sequence : std::false_type {};
0035 
0036 template <typename ...Ts>
0037 struct is_sequence<type_sequence<Ts...>> : std::true_type {};
0038 
0039 template <typename T, T ...Is>
0040 struct is_sequence<std::integer_sequence<T, Is...>> : std::true_type {};
0041 
0042 
0043 // number of elements in a sequence
0044 template <typename Sequence>
0045 struct sequence_size {};
0046 
0047 template <typename ...Ts>
0048 struct sequence_size<type_sequence<Ts...>>
0049     : std::integral_constant<std::size_t, sizeof...(Ts)>
0050 {};
0051 
0052 template <typename T, T ...Is>
0053 struct sequence_size<std::integer_sequence<T, Is...>>
0054     : std::integral_constant<std::size_t, sizeof...(Is)>
0055 {};
0056 
0057 
0058 // element of a sequence
0059 template <std::size_t I, typename Sequence>
0060 struct sequence_element {};
0061 
0062 template <std::size_t I, typename T, typename ...Ts>
0063 struct sequence_element<I, type_sequence<T, Ts...>>
0064 {
0065     using type = typename sequence_element<I - 1, type_sequence<Ts...>>::type;
0066 };
0067 
0068 template <typename T, typename ...Ts>
0069 struct sequence_element<0, type_sequence<T, Ts...>>
0070 {
0071     using type = T;
0072 };
0073 
0074 template <std::size_t I, typename T, T J, T ...Js>
0075 struct sequence_element<I, std::integer_sequence<T, J, Js...>>
0076     : std::integral_constant
0077         <
0078             T,
0079             sequence_element<I - 1, std::integer_sequence<T, Js...>>::value
0080         >
0081 {};
0082 
0083 template <typename T, T J, T ...Js>
0084 struct sequence_element<0, std::integer_sequence<T, J, Js...>>
0085     : std::integral_constant<T, J>
0086 {};
0087 
0088 
0089 template <typename ...Ts>
0090 struct pack_front
0091 {
0092     static_assert(sizeof...(Ts) > 0, "Parameter pack can not be empty.");
0093 };
0094 
0095 template <typename T, typename ... Ts>
0096 struct pack_front<T, Ts...>
0097 {
0098     typedef T type;
0099 };
0100 
0101 
0102 template <typename Sequence>
0103 struct sequence_front
0104     : sequence_element<0, Sequence>
0105 {
0106     static_assert(sequence_size<Sequence>::value > 0, "Sequence can not be empty.");
0107 };
0108 
0109 
0110 template <typename Sequence>
0111 struct sequence_back
0112     : sequence_element<sequence_size<Sequence>::value - 1, Sequence>
0113 {
0114     static_assert(sequence_size<Sequence>::value > 0, "Sequence can not be empty.");
0115 };
0116 
0117 
0118 template <typename Sequence>
0119 struct sequence_empty
0120     : std::integral_constant
0121         <
0122             bool,
0123             sequence_size<Sequence>::value == 0
0124         >
0125 {};
0126 
0127 
0128 // Defines type member for the first type in sequence that satisfies UnaryPred.
0129 template
0130 <
0131     typename Sequence,
0132     template <typename> class UnaryPred
0133 >
0134 struct sequence_find_if {};
0135 
0136 template
0137 <
0138     typename T, typename ...Ts,
0139     template <typename> class UnaryPred
0140 >
0141 struct sequence_find_if<type_sequence<T, Ts...>, UnaryPred>
0142     : std::conditional
0143         <
0144             UnaryPred<T>::value,
0145             T,
0146             // TODO: prevent instantiation for the rest of the sequence if value is true
0147             typename sequence_find_if<type_sequence<Ts...>, UnaryPred>::type
0148         >
0149 {};
0150 
0151 template <template <typename> class UnaryPred>
0152 struct sequence_find_if<type_sequence<>, UnaryPred>
0153 {
0154     // TODO: This is technically incorrect because void can be stored in a type_sequence
0155     using type = void;
0156 };
0157 
0158 
0159 // sequence_merge<type_sequence<A, B>, type_sequence<C, D>>::type is
0160 //   type_sequence<A, B, C, D>
0161 // sequence_merge<integer_sequence<A, B>, integer_sequence<C, D>>::type is
0162 //   integer_sequence<A, B, C, D>
0163 template <typename ...Sequences>
0164 struct sequence_merge;
0165 
0166 template <typename S>
0167 struct sequence_merge<S>
0168 {
0169     using type = S;
0170 };
0171 
0172 template <typename ...T1s, typename ...T2s>
0173 struct sequence_merge<type_sequence<T1s...>, type_sequence<T2s...>>
0174 {
0175     using type = type_sequence<T1s..., T2s...>;
0176 };
0177 
0178 template <typename T, T ...I1s, T ...I2s>
0179 struct sequence_merge<std::integer_sequence<T, I1s...>, std::integer_sequence<T, I2s...>>
0180 {
0181     using type = std::integer_sequence<T, I1s..., I2s...>;
0182 };
0183 
0184 template <typename S1, typename S2, typename ...Sequences>
0185 struct sequence_merge<S1, S2, Sequences...>
0186 {
0187     using type = typename sequence_merge
0188         <
0189             typename sequence_merge<S1, S2>::type,
0190             typename sequence_merge<Sequences...>::type
0191         >::type;
0192 };
0193 
0194 
0195 // sequence_combine<type_sequence<A, B>, type_sequence<C, D>>::type is
0196 //   type_sequence<type_sequence<A, C>, type_sequence<A, D>,
0197 //                 type_sequence<B, C>, type_sequence<B, D>>
0198 template <typename Sequence1, typename Sequence2>
0199 struct sequence_combine;
0200 
0201 template <typename ...T1s, typename ...T2s>
0202 struct sequence_combine<type_sequence<T1s...>, type_sequence<T2s...>>
0203 {
0204     template <typename T1>
0205     using type_sequence_t = type_sequence<type_sequence<T1, T2s>...>;
0206 
0207     using type = typename sequence_merge<type_sequence_t<T1s>...>::type;
0208 };
0209 
0210 // sequence_combine<integer_sequence<T, 1, 2>, integer_sequence<T, 3, 4>>::type is
0211 //   type_sequence<integer_sequence<T, 1, 3>, integer_sequence<T, 1, 4>,
0212 //                 integer_sequence<T, 2, 3>, integer_sequence<T, 2, 4>>
0213 template <typename T, T ...I1s, T ...I2s>
0214 struct sequence_combine<std::integer_sequence<T, I1s...>, std::integer_sequence<T, I2s...>>
0215 {
0216     template <T I1>
0217     using type_sequence_t = type_sequence<std::integer_sequence<T, I1, I2s>...>;
0218 
0219     using type = typename sequence_merge<type_sequence_t<I1s>...>::type;
0220 };
0221 
0222 
0223 // Selects least element from a parameter pack based on
0224 // LessPred<T1, T2>::value comparison, similar to std::min_element
0225 template
0226 <
0227     template <typename, typename> class LessPred,
0228     typename ...Ts
0229 >
0230 struct pack_min_element;
0231 
0232 template
0233 <
0234     template <typename, typename> class LessPred,
0235     typename T
0236 >
0237 struct pack_min_element<LessPred, T>
0238 {
0239     using type = T;
0240 };
0241 
0242 template
0243 <
0244     template <typename, typename> class LessPred,
0245     typename T1, typename T2
0246 >
0247 struct pack_min_element<LessPred, T1, T2>
0248 {
0249     using type = std::conditional_t<LessPred<T1, T2>::value, T1, T2>;
0250 };
0251 
0252 template
0253 <
0254     template <typename, typename> class LessPred,
0255     typename T1, typename T2, typename ...Ts
0256 >
0257 struct pack_min_element<LessPred, T1, T2, Ts...>
0258 {
0259     using type = typename pack_min_element
0260         <
0261             LessPred,
0262             typename pack_min_element<LessPred, T1, T2>::type,
0263             typename pack_min_element<LessPred, Ts...>::type
0264         >::type;
0265 };
0266 
0267 
0268 // Selects least element from a sequence based on
0269 // LessPred<T1, T2>::value comparison, similar to std::min_element
0270 template
0271 <
0272     typename Sequence,
0273     template <typename, typename> class LessPred
0274 >
0275 struct sequence_min_element;
0276 
0277 template
0278 <
0279     typename ...Ts,
0280     template <typename, typename> class LessPred
0281 >
0282 struct sequence_min_element<type_sequence<Ts...>, LessPred>
0283 {
0284     using type = typename pack_min_element<LessPred, Ts...>::type;
0285 };
0286 
0287 
0288 // TODO: Since there are two kinds of parameter packs and sequences there probably should be two
0289 //   versions of sequence_find_if as well as parameter_pack_min_element and sequence_min_element.
0290 //   Currently these utilities support only types.
0291 
0292 
0293 } // namespace util
0294 
0295 
0296 }} // namespace boost::geometry
0297 
0298 
0299 #endif // BOOST_GEOMETRY_UTIL_SEQUENCE_HPP