]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/hana/include/boost/hana/filter.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / hana / include / boost / hana / filter.hpp
1 /*!
2 @file
3 Defines `boost::hana::filter`.
4
5 @copyright Louis Dionne 2013-2016
6 Distributed under the Boost Software License, Version 1.0.
7 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
8 */
9
10 #ifndef BOOST_HANA_FILTER_HPP
11 #define BOOST_HANA_FILTER_HPP
12
13 #include <boost/hana/fwd/filter.hpp>
14
15 #include <boost/hana/at.hpp>
16 #include <boost/hana/bool.hpp>
17 #include <boost/hana/chain.hpp>
18 #include <boost/hana/concept/monad_plus.hpp>
19 #include <boost/hana/concept/sequence.hpp>
20 #include <boost/hana/config.hpp>
21 #include <boost/hana/core/dispatch.hpp>
22 #include <boost/hana/core/make.hpp>
23 #include <boost/hana/detail/algorithm.hpp>
24 #include <boost/hana/detail/array.hpp>
25 #include <boost/hana/detail/decay.hpp>
26 #include <boost/hana/empty.hpp>
27 #include <boost/hana/lift.hpp>
28 #include <boost/hana/unpack.hpp>
29
30 #include <cstddef>
31 #include <utility>
32
33
34 BOOST_HANA_NAMESPACE_BEGIN
35 //! @cond
36 template <typename Xs, typename Pred>
37 constexpr auto filter_t::operator()(Xs&& xs, Pred&& pred) const {
38 using M = typename hana::tag_of<Xs>::type;
39 using Filter = BOOST_HANA_DISPATCH_IF(filter_impl<M>,
40 hana::MonadPlus<M>::value
41 );
42
43 #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
44 static_assert(hana::MonadPlus<M>::value,
45 "hana::filter(xs, pred) requires 'xs' to be a MonadPlus");
46 #endif
47
48 return Filter::apply(static_cast<Xs&&>(xs),
49 static_cast<Pred&&>(pred));
50 }
51 //! @endcond
52
53 namespace detail {
54 template <typename Pred, typename M>
55 struct lift_or_empty {
56 template <typename X>
57 static constexpr auto helper(X&& x, hana::true_)
58 { return hana::lift<M>(static_cast<X&&>(x)); }
59
60 template <typename X>
61 static constexpr auto helper(X&&, hana::false_)
62 { return hana::empty<M>(); }
63
64 template <typename X>
65 constexpr auto operator()(X&& x) const {
66 constexpr bool cond = decltype(std::declval<Pred>()(x))::value;
67 return helper(static_cast<X&&>(x), hana::bool_c<cond>);
68 }
69 };
70 }
71
72 template <typename M, bool condition>
73 struct filter_impl<M, when<condition>> : default_ {
74 template <typename Xs, typename Pred>
75 static constexpr decltype(auto) apply(Xs&& xs, Pred const&) {
76 return hana::chain(static_cast<Xs&&>(xs),
77 detail::lift_or_empty<Pred, M>{}
78 );
79 }
80 };
81
82 namespace detail {
83 template <bool ...b>
84 struct filter_indices {
85 static constexpr auto compute_indices() {
86 constexpr bool bs[] = {b..., false}; // avoid empty array
87 constexpr std::size_t N = detail::count(bs, bs + sizeof(bs), true);
88 detail::array<std::size_t, N> indices{};
89 std::size_t* keep = &indices[0];
90 for (std::size_t i = 0; i < sizeof...(b); ++i)
91 if (bs[i])
92 *keep++ = i;
93 return indices;
94 }
95
96 static constexpr auto indices = compute_indices();
97 };
98
99 template <typename Pred>
100 struct make_filter_indices {
101 Pred const& pred;
102 template <typename ...X>
103 auto operator()(X&& ...x) const -> filter_indices<
104 static_cast<bool>(detail::decay<
105 decltype(pred(static_cast<X&&>(x)))
106 >::type::value)...
107 > { return {}; }
108 };
109 }
110
111 template <typename S>
112 struct filter_impl<S, when<Sequence<S>::value>> {
113 template <typename Indices, typename Xs, std::size_t ...i>
114 static constexpr auto filter_helper(Xs&& xs, std::index_sequence<i...>) {
115 return hana::make<S>(
116 hana::at_c<Indices::indices[i]>(static_cast<Xs&&>(xs))...
117 );
118 }
119
120 template <typename Xs, typename Pred>
121 static constexpr auto apply(Xs&& xs, Pred const& pred) {
122 using Indices = decltype(
123 hana::unpack(static_cast<Xs&&>(xs),
124 detail::make_filter_indices<Pred>{pred})
125 );
126
127 return filter_impl::filter_helper<Indices>(
128 static_cast<Xs&&>(xs),
129 std::make_index_sequence<Indices::indices.size()>{}
130 );
131 }
132 };
133 BOOST_HANA_NAMESPACE_END
134
135 #endif // !BOOST_HANA_FILTER_HPP