any_of.hpp 7.5 KB

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