File indexing completed on 2025-01-18 09:38:04
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_HANA_PARTITION_HPP
0011 #define BOOST_HANA_PARTITION_HPP
0012
0013 #include <boost/hana/fwd/partition.hpp>
0014
0015 #include <boost/hana/at.hpp>
0016 #include <boost/hana/concept/sequence.hpp>
0017 #include <boost/hana/config.hpp>
0018 #include <boost/hana/core/dispatch.hpp>
0019 #include <boost/hana/core/make.hpp>
0020 #include <boost/hana/detail/algorithm.hpp>
0021 #include <boost/hana/detail/array.hpp>
0022 #include <boost/hana/detail/decay.hpp>
0023 #include <boost/hana/detail/nested_by.hpp> // required by fwd decl
0024 #include <boost/hana/pair.hpp>
0025 #include <boost/hana/unpack.hpp>
0026
0027 #include <cstddef>
0028 #include <utility>
0029
0030
0031 namespace boost { namespace hana {
0032
0033 template <typename Xs, typename Pred>
0034 constexpr auto partition_t::operator()(Xs&& xs, Pred&& pred) const {
0035 using S = typename hana::tag_of<Xs>::type;
0036 using Partition = BOOST_HANA_DISPATCH_IF(partition_impl<S>,
0037 hana::Sequence<S>::value
0038 );
0039
0040 #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
0041 static_assert(hana::Sequence<S>::value,
0042 "hana::partition(xs, pred) requires 'xs' to be a Sequence");
0043 #endif
0044
0045 return Partition::apply(static_cast<Xs&&>(xs), static_cast<Pred&&>(pred));
0046 }
0047
0048
0049 namespace detail {
0050 template <bool ...B>
0051 struct partition_indices {
0052 static constexpr detail::array<bool, sizeof...(B)> results{{B...}};
0053 static constexpr std::size_t left_size =
0054 detail::count(results.begin(), results.end(), true);
0055 static constexpr std::size_t right_size = sizeof...(B) - left_size;
0056
0057 static constexpr auto compute_left() {
0058 detail::array<std::size_t, left_size> indices{};
0059 std::size_t* left = &indices[0];
0060 for (std::size_t i = 0; i < sizeof...(B); ++i)
0061 if (results[i])
0062 *left++ = i;
0063 return indices;
0064 }
0065
0066 static constexpr auto compute_right() {
0067 detail::array<std::size_t, right_size> indices{};
0068 std::size_t* right = &indices[0];
0069 for (std::size_t i = 0; i < sizeof...(B); ++i)
0070 if (!results[i])
0071 *right++ = i;
0072 return indices;
0073 }
0074
0075 static constexpr auto left_indices = compute_left();
0076 static constexpr auto right_indices = compute_right();
0077
0078 template <typename S, typename Xs, std::size_t ...l, std::size_t ...r>
0079 static constexpr auto apply(Xs&& xs, std::index_sequence<l...>,
0080 std::index_sequence<r...>)
0081 {
0082 return hana::make<hana::pair_tag>(
0083 hana::make<S>(hana::at_c<left_indices[l]>(static_cast<Xs&&>(xs))...),
0084 hana::make<S>(hana::at_c<right_indices[r]>(static_cast<Xs&&>(xs))...)
0085 );
0086 }
0087 };
0088
0089 template <typename Pred>
0090 struct deduce_partition_indices {
0091 template <typename ...Xs>
0092 auto operator()(Xs&& ...xs) const -> detail::partition_indices<
0093 static_cast<bool>(detail::decay<
0094 decltype(std::declval<Pred>()(static_cast<Xs&&>(xs)))
0095 >::type::value)...
0096 > { return {}; }
0097 };
0098 }
0099
0100 template <typename S, bool condition>
0101 struct partition_impl<S, when<condition>> : default_ {
0102 template <typename Xs, typename Pred>
0103 static constexpr auto apply(Xs&& xs, Pred&&) {
0104 using Indices = decltype(hana::unpack(
0105 static_cast<Xs&&>(xs), detail::deduce_partition_indices<Pred&&>{}
0106 ));
0107 return Indices::template apply<S>(
0108 static_cast<Xs&&>(xs),
0109 std::make_index_sequence<Indices::left_size>{},
0110 std::make_index_sequence<Indices::right_size>{}
0111 );
0112 }
0113 };
0114 }}
0115
0116 #endif