123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299 |
- // Boost.Geometry
- // Copyright (c) 2020-2023, Oracle and/or its affiliates.
- // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
- // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
- // Licensed under the Boost Software License version 1.0.
- // http://www.boost.org/users/license.html
- #ifndef BOOST_GEOMETRY_UTIL_SEQUENCE_HPP
- #define BOOST_GEOMETRY_UTIL_SEQUENCE_HPP
- #include <utility>
- #include <type_traits>
- namespace boost { namespace geometry
- {
- namespace util
- {
- // An alternative would be to use std:tuple and std::pair
- // but it would add dependency.
- template <typename ...Ts>
- struct type_sequence {};
- // true if T is a sequence
- template <typename T>
- struct is_sequence : std::false_type {};
- template <typename ...Ts>
- struct is_sequence<type_sequence<Ts...>> : std::true_type {};
- template <typename T, T ...Is>
- struct is_sequence<std::integer_sequence<T, Is...>> : std::true_type {};
- // number of elements in a sequence
- template <typename Sequence>
- struct sequence_size {};
- template <typename ...Ts>
- struct sequence_size<type_sequence<Ts...>>
- : std::integral_constant<std::size_t, sizeof...(Ts)>
- {};
- template <typename T, T ...Is>
- struct sequence_size<std::integer_sequence<T, Is...>>
- : std::integral_constant<std::size_t, sizeof...(Is)>
- {};
- // element of a sequence
- template <std::size_t I, typename Sequence>
- struct sequence_element {};
- template <std::size_t I, typename T, typename ...Ts>
- struct sequence_element<I, type_sequence<T, Ts...>>
- {
- using type = typename sequence_element<I - 1, type_sequence<Ts...>>::type;
- };
- template <typename T, typename ...Ts>
- struct sequence_element<0, type_sequence<T, Ts...>>
- {
- using type = T;
- };
- template <std::size_t I, typename T, T J, T ...Js>
- struct sequence_element<I, std::integer_sequence<T, J, Js...>>
- : std::integral_constant
- <
- T,
- sequence_element<I - 1, std::integer_sequence<T, Js...>>::value
- >
- {};
- template <typename T, T J, T ...Js>
- struct sequence_element<0, std::integer_sequence<T, J, Js...>>
- : std::integral_constant<T, J>
- {};
- template <typename ...Ts>
- struct pack_front
- {
- static_assert(sizeof...(Ts) > 0, "Parameter pack can not be empty.");
- };
- template <typename T, typename ... Ts>
- struct pack_front<T, Ts...>
- {
- typedef T type;
- };
- template <typename Sequence>
- struct sequence_front
- : sequence_element<0, Sequence>
- {
- static_assert(sequence_size<Sequence>::value > 0, "Sequence can not be empty.");
- };
- template <typename Sequence>
- struct sequence_back
- : sequence_element<sequence_size<Sequence>::value - 1, Sequence>
- {
- static_assert(sequence_size<Sequence>::value > 0, "Sequence can not be empty.");
- };
- template <typename Sequence>
- struct sequence_empty
- : std::integral_constant
- <
- bool,
- sequence_size<Sequence>::value == 0
- >
- {};
- // Defines type member for the first type in sequence that satisfies UnaryPred.
- template
- <
- typename Sequence,
- template <typename> class UnaryPred
- >
- struct sequence_find_if {};
- template
- <
- typename T, typename ...Ts,
- template <typename> class UnaryPred
- >
- struct sequence_find_if<type_sequence<T, Ts...>, UnaryPred>
- : std::conditional
- <
- UnaryPred<T>::value,
- T,
- // TODO: prevent instantiation for the rest of the sequence if value is true
- typename sequence_find_if<type_sequence<Ts...>, UnaryPred>::type
- >
- {};
- template <template <typename> class UnaryPred>
- struct sequence_find_if<type_sequence<>, UnaryPred>
- {
- // TODO: This is technically incorrect because void can be stored in a type_sequence
- using type = void;
- };
- // sequence_merge<type_sequence<A, B>, type_sequence<C, D>>::type is
- // type_sequence<A, B, C, D>
- // sequence_merge<integer_sequence<A, B>, integer_sequence<C, D>>::type is
- // integer_sequence<A, B, C, D>
- template <typename ...Sequences>
- struct sequence_merge;
- template <typename S>
- struct sequence_merge<S>
- {
- using type = S;
- };
- template <typename ...T1s, typename ...T2s>
- struct sequence_merge<type_sequence<T1s...>, type_sequence<T2s...>>
- {
- using type = type_sequence<T1s..., T2s...>;
- };
- template <typename T, T ...I1s, T ...I2s>
- struct sequence_merge<std::integer_sequence<T, I1s...>, std::integer_sequence<T, I2s...>>
- {
- using type = std::integer_sequence<T, I1s..., I2s...>;
- };
- template <typename S1, typename S2, typename ...Sequences>
- struct sequence_merge<S1, S2, Sequences...>
- {
- using type = typename sequence_merge
- <
- typename sequence_merge<S1, S2>::type,
- typename sequence_merge<Sequences...>::type
- >::type;
- };
- // sequence_combine<type_sequence<A, B>, type_sequence<C, D>>::type is
- // type_sequence<type_sequence<A, C>, type_sequence<A, D>,
- // type_sequence<B, C>, type_sequence<B, D>>
- template <typename Sequence1, typename Sequence2>
- struct sequence_combine;
- template <typename ...T1s, typename ...T2s>
- struct sequence_combine<type_sequence<T1s...>, type_sequence<T2s...>>
- {
- template <typename T1>
- using type_sequence_t = type_sequence<type_sequence<T1, T2s>...>;
- using type = typename sequence_merge<type_sequence_t<T1s>...>::type;
- };
- // sequence_combine<integer_sequence<T, 1, 2>, integer_sequence<T, 3, 4>>::type is
- // type_sequence<integer_sequence<T, 1, 3>, integer_sequence<T, 1, 4>,
- // integer_sequence<T, 2, 3>, integer_sequence<T, 2, 4>>
- template <typename T, T ...I1s, T ...I2s>
- struct sequence_combine<std::integer_sequence<T, I1s...>, std::integer_sequence<T, I2s...>>
- {
- template <T I1>
- using type_sequence_t = type_sequence<std::integer_sequence<T, I1, I2s>...>;
- using type = typename sequence_merge<type_sequence_t<I1s>...>::type;
- };
- // Selects least element from a parameter pack based on
- // LessPred<T1, T2>::value comparison, similar to std::min_element
- template
- <
- template <typename, typename> class LessPred,
- typename ...Ts
- >
- struct pack_min_element;
- template
- <
- template <typename, typename> class LessPred,
- typename T
- >
- struct pack_min_element<LessPred, T>
- {
- using type = T;
- };
- template
- <
- template <typename, typename> class LessPred,
- typename T1, typename T2
- >
- struct pack_min_element<LessPred, T1, T2>
- {
- using type = std::conditional_t<LessPred<T1, T2>::value, T1, T2>;
- };
- template
- <
- template <typename, typename> class LessPred,
- typename T1, typename T2, typename ...Ts
- >
- struct pack_min_element<LessPred, T1, T2, Ts...>
- {
- using type = typename pack_min_element
- <
- LessPred,
- typename pack_min_element<LessPred, T1, T2>::type,
- typename pack_min_element<LessPred, Ts...>::type
- >::type;
- };
- // Selects least element from a sequence based on
- // LessPred<T1, T2>::value comparison, similar to std::min_element
- template
- <
- typename Sequence,
- template <typename, typename> class LessPred
- >
- struct sequence_min_element;
- template
- <
- typename ...Ts,
- template <typename, typename> class LessPred
- >
- struct sequence_min_element<type_sequence<Ts...>, LessPred>
- {
- using type = typename pack_min_element<LessPred, Ts...>::type;
- };
- // TODO: Since there are two kinds of parameter packs and sequences there probably should be two
- // versions of sequence_find_if as well as parameter_pack_min_element and sequence_min_element.
- // Currently these utilities support only types.
- } // namespace util
- }} // namespace boost::geometry
- #endif // BOOST_GEOMETRY_UTIL_SEQUENCE_HPP
|