find_if.hpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. /*!
  2. @file
  3. Defines `boost::hana::find_if`.
  4. Copyright Louis Dionne 2013-2022
  5. Copyright Jason Rice 2017
  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. #ifndef BOOST_HANA_FIND_IF_HPP
  10. #define BOOST_HANA_FIND_IF_HPP
  11. #include <boost/hana/fwd/find_if.hpp>
  12. #include <boost/hana/accessors.hpp>
  13. #include <boost/hana/at.hpp>
  14. #include <boost/hana/bool.hpp>
  15. #include <boost/hana/concept/iterable.hpp>
  16. #include <boost/hana/concept/searchable.hpp>
  17. #include <boost/hana/concept/struct.hpp>
  18. #include <boost/hana/config.hpp>
  19. #include <boost/hana/core/dispatch.hpp>
  20. #include <boost/hana/first.hpp>
  21. #include <boost/hana/functional/compose.hpp>
  22. #include <boost/hana/index_if.hpp>
  23. #include <boost/hana/second.hpp>
  24. #include <boost/hana/transform.hpp>
  25. #include <cstddef>
  26. #include <utility>
  27. namespace boost { namespace hana {
  28. //! @cond
  29. template <typename Xs, typename Pred>
  30. constexpr auto find_if_t::operator()(Xs&& xs, Pred&& pred) const {
  31. using S = typename hana::tag_of<Xs>::type;
  32. using FindIf = BOOST_HANA_DISPATCH_IF(find_if_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::find_if(xs, pred) requires 'xs' to be a Searchable");
  38. #endif
  39. return FindIf::apply(static_cast<Xs&&>(xs), static_cast<Pred&&>(pred));
  40. }
  41. //! @endcond
  42. template <typename S, bool condition>
  43. struct find_if_impl<S, when<condition>> : default_ {
  44. template <typename ...Args>
  45. static constexpr auto apply(Args&& ...) = delete;
  46. };
  47. namespace detail {
  48. template <typename Xs>
  49. struct partial_at {
  50. Xs const& xs;
  51. template <typename I>
  52. constexpr decltype(auto) operator()(I i) const {
  53. return hana::at(xs, i);
  54. }
  55. };
  56. }
  57. template <typename Tag>
  58. struct find_if_impl<Tag, when<Iterable<Tag>::value>> {
  59. template <typename Xs, typename Pred>
  60. static constexpr auto apply(Xs&& xs, Pred&& pred) {
  61. using Result = decltype(hana::index_if(
  62. static_cast<Xs&&>(xs), static_cast<Pred&&>(pred)));
  63. return hana::transform(Result{},
  64. detail::partial_at<std::decay_t<Xs>>{static_cast<Xs&&>(xs)});
  65. }
  66. };
  67. template <typename T, std::size_t N>
  68. struct find_if_impl<T[N]> {
  69. template <typename Xs>
  70. static constexpr auto find_if_helper(Xs&&, hana::false_)
  71. { return hana::nothing; }
  72. template <typename Xs>
  73. static constexpr auto find_if_helper(Xs&& xs, hana::true_)
  74. { return hana::just(static_cast<Xs&&>(xs)[0]); }
  75. template <typename Xs, typename Pred>
  76. static constexpr auto apply(Xs&& xs, Pred&& pred) {
  77. return find_if_helper(static_cast<Xs&&>(xs),
  78. hana::bool_c<decltype(
  79. static_cast<Pred&&>(pred)(static_cast<Xs&&>(xs)[0])
  80. )::value>
  81. );
  82. }
  83. };
  84. namespace struct_detail {
  85. template <typename X>
  86. struct get_member {
  87. X x;
  88. template <typename Member>
  89. constexpr decltype(auto) operator()(Member&& member) && {
  90. return hana::second(static_cast<Member&&>(member))(
  91. static_cast<X&&>(x)
  92. );
  93. }
  94. };
  95. }
  96. template <typename S>
  97. struct find_if_impl<S, when<hana::Struct<S>::value>> {
  98. template <typename X, typename Pred>
  99. static constexpr decltype(auto) apply(X&& x, Pred&& pred) {
  100. return hana::transform(
  101. hana::find_if(hana::accessors<S>(),
  102. hana::compose(static_cast<Pred&&>(pred), hana::first)
  103. ),
  104. struct_detail::get_member<X>{static_cast<X&&>(x)}
  105. );
  106. }
  107. };
  108. }} // end namespace boost::hana
  109. #endif // !BOOST_HANA_FIND_IF_HPP