any_of.hpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /*!
  2. @file
  3. Defines `boost::hana::any_of`.
  4. @copyright Louis Dionne 2013-2017
  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. return prev_cond ? hana::true_c
  55. : any_of_impl::any_of_helper<k + 1, Len>::apply(
  56. hana::if_(pred(hana::at_c<k>(xs)), hana::true_c, hana::false_c),
  57. static_cast<Xs&&>(xs),
  58. static_cast<Pred&&>(pred)
  59. );
  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. decltype(auto) tail = hana::drop_front(static_cast<Xs&&>(xs));
  96. constexpr bool done = decltype(hana::is_empty(tail))::value;
  97. return prev_cond ? hana::true_c
  98. : lazy_any_of_helper(hana::bool_<done>{},
  99. hana::if_(pred(hana::front(xs)), hana::true_{}, hana::false_{}),
  100. static_cast<decltype(tail)&&>(tail),
  101. static_cast<Pred&&>(pred)
  102. );
  103. }
  104. template <typename Xs, typename Pred>
  105. static constexpr auto lazy_any_of_helper(hana::false_, hana::true_, Xs&&, Pred&&)
  106. { return hana::true_c; }
  107. template <typename Xs, typename Pred>
  108. static constexpr auto lazy_any_of_helper(hana::false_, hana::false_, Xs&& xs, Pred&& pred) {
  109. constexpr bool done = decltype(hana::is_empty(hana::drop_front(xs)))::value;
  110. return lazy_any_of_helper(hana::bool_c<done>,
  111. hana::if_(pred(hana::front(xs)), hana::true_c, hana::false_c),
  112. hana::drop_front(static_cast<Xs&&>(xs)),
  113. static_cast<Pred&&>(pred)
  114. );
  115. }
  116. template <typename Cond, typename Xs, typename Pred>
  117. static constexpr auto lazy_any_of_helper(hana::true_, Cond cond, Xs&&, Pred&&)
  118. { return cond; }
  119. template <typename Xs, typename Pred>
  120. static constexpr auto apply(Xs&& xs, Pred&& pred) {
  121. constexpr bool done = decltype(hana::is_empty(xs))::value;
  122. return lazy_any_of_helper(hana::bool_c<done>, hana::false_c,
  123. static_cast<Xs&&>(xs),
  124. static_cast<Pred&&>(pred));
  125. }
  126. };
  127. template <typename T, std::size_t N>
  128. struct any_of_impl<T[N]> {
  129. template <typename Xs, typename Pred>
  130. static constexpr bool any_of_helper(bool cond, Xs&& xs, Pred&& pred) {
  131. if (cond) return true;
  132. for (std::size_t i = 1; i < N; ++i)
  133. if (pred(static_cast<Xs&&>(xs)[i]))
  134. return true;
  135. return false;
  136. }
  137. // Since an array contains homogeneous data, if the predicate returns
  138. // a compile-time logical at any index, it must do so at every index
  139. // (because the type of the elements won't change)! In this case, we
  140. // then only need to evaluate the predicate on the first element.
  141. template <typename Xs, typename Pred>
  142. static constexpr auto
  143. any_of_helper(hana::true_, Xs&& /*xs*/, Pred&&)
  144. { return hana::true_c; }
  145. template <typename Xs, typename Pred>
  146. static constexpr auto
  147. any_of_helper(hana::false_, Xs&&, Pred&&)
  148. { return hana::false_c; }
  149. template <typename Xs, typename Pred>
  150. static constexpr auto apply(Xs&& xs, Pred&& pred) {
  151. auto cond = hana::if_(pred(static_cast<Xs&&>(xs)[0]), hana::true_c,
  152. hana::false_c);
  153. return any_of_helper(cond, static_cast<Xs&&>(xs),
  154. static_cast<Pred&&>(pred));
  155. }
  156. };
  157. template <typename S>
  158. struct any_of_impl<S, when<hana::Struct<S>::value>> {
  159. template <typename X, typename Pred>
  160. static constexpr decltype(auto) apply(X const&, Pred&& pred) {
  161. return hana::any_of(hana::accessors<S>(),
  162. hana::compose(static_cast<Pred&&>(pred), hana::first));
  163. }
  164. };
  165. BOOST_HANA_NAMESPACE_END
  166. #endif // !BOOST_HANA_ANY_OF_HPP