// Boost.Geometry // Copyright (c) 2020, Oracle and/or its affiliates. // 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 namespace boost { namespace geometry { namespace util { // An alternative would be to use std:tuple and std::pair // but it would add dependency. template struct type_sequence {}; // true if T is a sequence template struct is_sequence : std::false_type {}; template struct is_sequence> : std::true_type {}; template struct is_sequence> : std::true_type {}; // number of elements in a sequence template struct sequence_size {}; template struct sequence_size> : std::integral_constant {}; template struct sequence_size> : std::integral_constant {}; // element of a sequence template struct sequence_element {}; template struct sequence_element> { typedef typename sequence_element>::type type; }; template struct sequence_element<0, type_sequence> { typedef T type; }; template struct sequence_element> : std::integral_constant < T, sequence_element>::value > {}; template struct sequence_element<0, std::integer_sequence> : std::integral_constant {}; template struct sequence_front : sequence_element<0, Sequence> { static_assert(sequence_size::value > 0, "Sequence can not be empty."); }; template struct sequence_back : sequence_element::value - 1, Sequence> { static_assert(sequence_size::value > 0, "Sequence can not be empty."); }; template struct sequence_empty : std::integral_constant < bool, sequence_size::value == 0 > {}; // merge, type_sequence>::type is // type_sequence // merge, integer_sequence>::type is // integer_sequence template struct merge; template struct merge { typedef S type; }; template struct merge, type_sequence> { typedef type_sequence type; }; template struct merge, std::integer_sequence> { typedef std::integer_sequence type; }; template struct merge { typedef typename merge < typename merge::type, typename merge::type >::type type; }; // combine, type_sequence>::type is // type_sequence, type_sequence, // type_sequence, type_sequence> template struct combine; template struct combine, type_sequence> { template using type_sequence_t = type_sequence...>; typedef typename merge < type_sequence_t... >::type type; }; // combine, integer_sequence>::type is // type_sequence, integer_sequence, // integer_sequence, integer_sequence> template struct combine, std::integer_sequence> { template using type_sequence_t = type_sequence...>; typedef typename merge < type_sequence_t... >::type type; }; // Selects least element from a parameter pack based on // LessPred::value comparison, similar to std::min_element template < template class LessPred, typename ...Ts > struct select_pack_element; template < template class LessPred, typename T > struct select_pack_element { typedef T type; }; template < template class LessPred, typename T1, typename T2 > struct select_pack_element { typedef std::conditional_t::value, T1, T2> type; }; template < template class LessPred, typename T1, typename T2, typename ...Ts > struct select_pack_element { typedef typename select_pack_element < LessPred, typename select_pack_element::type, typename select_pack_element::type >::type type; }; // Selects least element from a sequence based on // LessPred::value comparison, similar to std::min_element template < typename Sequence, template class LessPred > struct select_element; template < typename ...Ts, template class LessPred > struct select_element, LessPred> { typedef typename select_pack_element::type type; }; // Selects least pair sequence of elements from a parameter pack based on // LessPred, xxx_sequence>::value comparison template < typename Sequence1, typename Sequence2, template class LessPred > struct select_combination_element { typedef typename select_element < typename combine::type, LessPred >::type type; }; } // namespace util }} // namespace boost::geometry #endif // BOOST_GEOMETRY_UTIL_SEQUENCE_HPP