]>
Commit | Line | Data |
---|---|---|
1 | /*! | |
2 | @file | |
3 | Defines `boost::hana::any_of`. | |
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_ANY_OF_HPP | |
11 | #define BOOST_HANA_ANY_OF_HPP | |
12 | ||
13 | #include <boost/hana/fwd/any_of.hpp> | |
14 | ||
15 | #include <boost/hana/accessors.hpp> | |
16 | #include <boost/hana/at.hpp> | |
17 | #include <boost/hana/bool.hpp> | |
18 | #include <boost/hana/concept/searchable.hpp> | |
19 | #include <boost/hana/concept/sequence.hpp> | |
20 | #include <boost/hana/concept/struct.hpp> | |
21 | #include <boost/hana/config.hpp> | |
22 | #include <boost/hana/core/dispatch.hpp> | |
23 | #include <boost/hana/drop_front.hpp> | |
24 | #include <boost/hana/first.hpp> | |
25 | #include <boost/hana/front.hpp> | |
26 | #include <boost/hana/functional/compose.hpp> | |
27 | #include <boost/hana/if.hpp> | |
28 | #include <boost/hana/is_empty.hpp> | |
29 | #include <boost/hana/length.hpp> | |
30 | ||
31 | #include <cstddef> | |
32 | ||
33 | ||
34 | BOOST_HANA_NAMESPACE_BEGIN | |
35 | //! @cond | |
36 | template <typename Xs, typename Pred> | |
37 | constexpr auto any_of_t::operator()(Xs&& xs, Pred&& pred) const { | |
38 | using S = typename hana::tag_of<Xs>::type; | |
39 | using AnyOf = BOOST_HANA_DISPATCH_IF(any_of_impl<S>, | |
40 | hana::Searchable<S>::value | |
41 | ); | |
42 | ||
43 | #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS | |
44 | static_assert(hana::Searchable<S>::value, | |
45 | "hana::any_of(xs, pred) requires 'xs' to be a Searchable"); | |
46 | #endif | |
47 | ||
48 | return AnyOf::apply(static_cast<Xs&&>(xs), static_cast<Pred&&>(pred)); | |
49 | } | |
50 | //! @endcond | |
51 | ||
52 | template <typename S, bool condition> | |
53 | struct any_of_impl<S, when<condition>> : default_ { | |
54 | template <typename ...Args> | |
55 | static constexpr auto apply(Args&& ...) = delete; | |
56 | }; | |
57 | ||
58 | template <typename S> | |
59 | struct any_of_impl<S, when<Sequence<S>::value>> { | |
60 | //! @cond | |
61 | template <std::size_t k, std::size_t Len> | |
62 | struct any_of_helper { | |
63 | template <typename Xs, typename Pred> | |
64 | static constexpr auto apply(bool prev_cond, Xs&& xs, Pred&& pred) { | |
65 | auto cond = hana::if_(pred(hana::at_c<k>(xs)), hana::true_c, | |
66 | hana::false_c); | |
67 | return prev_cond ? hana::true_c | |
68 | : any_of_impl::any_of_helper<k + 1, Len>::apply(cond, | |
69 | static_cast<Xs&&>(xs), | |
70 | static_cast<Pred&&>(pred)); | |
71 | } | |
72 | ||
73 | template <typename Xs, typename Pred> | |
74 | static constexpr auto apply(hana::true_, Xs&&, Pred&&) | |
75 | { return hana::true_c; } | |
76 | ||
77 | template <typename Xs, typename Pred> | |
78 | static constexpr auto apply(hana::false_, Xs&& xs, Pred&& pred) { | |
79 | auto cond = hana::if_(pred(hana::at_c<k>(xs)), hana::true_c, | |
80 | hana::false_c); | |
81 | return any_of_impl::any_of_helper<k + 1, Len>::apply(cond, | |
82 | static_cast<Xs&&>(xs), | |
83 | static_cast<Pred&&>(pred)); | |
84 | } | |
85 | }; | |
86 | ||
87 | template <std::size_t Len> | |
88 | struct any_of_helper<Len, Len> { | |
89 | template <typename Cond, typename Xs, typename Pred> | |
90 | static constexpr auto apply(Cond cond, Xs&&, Pred&&) | |
91 | { return cond; } | |
92 | }; | |
93 | ||
94 | template <typename Xs, typename Pred> | |
95 | static constexpr auto apply(Xs&& xs, Pred&& pred) { | |
96 | constexpr std::size_t len = decltype(hana::length(xs))::value; | |
97 | return any_of_impl::any_of_helper<0, len>::apply(hana::false_c, | |
98 | static_cast<Xs&&>(xs), | |
99 | static_cast<Pred&&>(pred)); | |
100 | } | |
101 | //! @endcond | |
102 | }; | |
103 | ||
104 | template <typename It> | |
105 | struct any_of_impl<It, when< | |
106 | hana::Iterable<It>::value && | |
107 | !Sequence<It>::value | |
108 | >> { | |
109 | template <typename Xs, typename Pred> | |
110 | static constexpr auto lazy_any_of_helper(hana::false_, bool prev_cond, Xs&& xs, Pred&& pred) { | |
111 | auto cond = hana::if_(pred(hana::front(xs)), hana::true_c, hana::false_c); | |
112 | decltype(auto) tail = hana::drop_front(static_cast<Xs&&>(xs)); | |
113 | constexpr bool done = decltype(hana::is_empty(tail))::value; | |
114 | return prev_cond ? hana::true_c | |
115 | : lazy_any_of_helper(hana::bool_c<done>, cond, | |
116 | static_cast<decltype(tail)&&>(tail), | |
117 | static_cast<Pred&&>(pred)); | |
118 | } | |
119 | ||
120 | template <typename Xs, typename Pred> | |
121 | static constexpr auto lazy_any_of_helper(hana::false_, hana::true_, Xs&&, Pred&&) | |
122 | { return hana::true_c; } | |
123 | ||
124 | template <typename Xs, typename Pred> | |
125 | static constexpr auto lazy_any_of_helper(hana::false_, hana::false_, Xs&& xs, Pred&& pred) { | |
126 | auto cond = hana::if_(pred(hana::front(xs)), hana::true_c, hana::false_c); | |
127 | constexpr bool done = decltype(hana::is_empty(hana::drop_front(xs)))::value; | |
128 | return lazy_any_of_helper(hana::bool_c<done>, cond, | |
129 | hana::drop_front(static_cast<Xs&&>(xs)), | |
130 | static_cast<Pred&&>(pred)); | |
131 | } | |
132 | ||
133 | template <typename Cond, typename Xs, typename Pred> | |
134 | static constexpr auto lazy_any_of_helper(hana::true_, Cond cond, Xs&&, Pred&&) | |
135 | { return cond; } | |
136 | ||
137 | template <typename Xs, typename Pred> | |
138 | static constexpr auto apply(Xs&& xs, Pred&& pred) { | |
139 | constexpr bool done = decltype(hana::is_empty(xs))::value; | |
140 | return lazy_any_of_helper(hana::bool_c<done>, hana::false_c, | |
141 | static_cast<Xs&&>(xs), | |
142 | static_cast<Pred&&>(pred)); | |
143 | } | |
144 | }; | |
145 | ||
146 | template <typename T, std::size_t N> | |
147 | struct any_of_impl<T[N]> { | |
148 | template <typename Xs, typename Pred> | |
149 | static constexpr bool any_of_helper(bool cond, Xs&& xs, Pred&& pred) { | |
150 | if (cond) return true; | |
151 | for (std::size_t i = 1; i < N; ++i) | |
152 | if (pred(static_cast<Xs&&>(xs)[i])) | |
153 | return true; | |
154 | return false; | |
155 | } | |
156 | ||
157 | // Since an array contains homogeneous data, if the predicate returns | |
158 | // a compile-time logical at any index, it must do so at every index | |
159 | // (because the type of the elements won't change)! In this case, we | |
160 | // then only need to evaluate the predicate on the first element. | |
161 | template <typename Xs, typename Pred> | |
162 | static constexpr auto | |
163 | any_of_helper(hana::true_, Xs&& /*xs*/, Pred&&) | |
164 | { return hana::true_c; } | |
165 | ||
166 | template <typename Xs, typename Pred> | |
167 | static constexpr auto | |
168 | any_of_helper(hana::false_, Xs&&, Pred&&) | |
169 | { return hana::false_c; } | |
170 | ||
171 | template <typename Xs, typename Pred> | |
172 | static constexpr auto apply(Xs&& xs, Pred&& pred) { | |
173 | auto cond = hana::if_(pred(static_cast<Xs&&>(xs)[0]), hana::true_c, | |
174 | hana::false_c); | |
175 | return any_of_helper(cond, static_cast<Xs&&>(xs), | |
176 | static_cast<Pred&&>(pred)); | |
177 | } | |
178 | }; | |
179 | ||
180 | template <typename S> | |
181 | struct any_of_impl<S, when<hana::Struct<S>::value>> { | |
182 | template <typename X, typename Pred> | |
183 | static constexpr decltype(auto) apply(X const&, Pred&& pred) { | |
184 | return hana::any_of(hana::accessors<S>(), | |
185 | hana::compose(static_cast<Pred&&>(pred), hana::first)); | |
186 | } | |
187 | }; | |
188 | BOOST_HANA_NAMESPACE_END | |
189 | ||
190 | #endif // !BOOST_HANA_ANY_OF_HPP |