• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*!
2 @file
3 Defines `boost::hana::find_if`.
4 
5 @copyright Louis Dionne 2013-2017
6 @copyright Jason Rice 2017
7 Distributed under the Boost Software License, Version 1.0.
8 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
9  */
10 
11 #ifndef BOOST_HANA_FIND_IF_HPP
12 #define BOOST_HANA_FIND_IF_HPP
13 
14 #include <boost/hana/fwd/find_if.hpp>
15 
16 #include <boost/hana/accessors.hpp>
17 #include <boost/hana/at.hpp>
18 #include <boost/hana/bool.hpp>
19 #include <boost/hana/concept/iterable.hpp>
20 #include <boost/hana/concept/searchable.hpp>
21 #include <boost/hana/concept/struct.hpp>
22 #include <boost/hana/config.hpp>
23 #include <boost/hana/core/dispatch.hpp>
24 #include <boost/hana/first.hpp>
25 #include <boost/hana/functional/compose.hpp>
26 #include <boost/hana/index_if.hpp>
27 #include <boost/hana/second.hpp>
28 #include <boost/hana/transform.hpp>
29 
30 #include <cstddef>
31 #include <utility>
32 
33 
34 BOOST_HANA_NAMESPACE_BEGIN
35     //! @cond
36     template <typename Xs, typename Pred>
operator ()(Xs && xs,Pred && pred) const37     constexpr auto find_if_t::operator()(Xs&& xs, Pred&& pred) const {
38         using S = typename hana::tag_of<Xs>::type;
39         using FindIf = BOOST_HANA_DISPATCH_IF(find_if_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::find_if(xs, pred) requires 'xs' to be a Searchable");
46     #endif
47 
48         return FindIf::apply(static_cast<Xs&&>(xs), static_cast<Pred&&>(pred));
49     }
50     //! @endcond
51 
52     template <typename S, bool condition>
53     struct find_if_impl<S, when<condition>> : default_ {
54         template <typename ...Args>
55         static constexpr auto apply(Args&& ...) = delete;
56     };
57 
58     namespace detail {
59         template <typename Xs>
60         struct partial_at {
61             Xs const& xs;
62 
63             template <typename I>
operator ()detail::partial_at64             constexpr decltype(auto) operator()(I i) const {
65                 return hana::at(xs, i);
66             }
67         };
68     }
69 
70     template <typename Tag>
71     struct find_if_impl<Tag, when<Iterable<Tag>::value>> {
72         template <typename Xs, typename Pred>
applyfind_if_impl73         static constexpr auto apply(Xs&& xs, Pred&& pred) {
74             using Result = decltype(hana::index_if(
75                 static_cast<Xs&&>(xs), static_cast<Pred&&>(pred)));
76 
77             return hana::transform(Result{},
78                 detail::partial_at<std::decay_t<Xs>>{static_cast<Xs&&>(xs)});
79         }
80     };
81 
82     template <typename T, std::size_t N>
83     struct find_if_impl<T[N]> {
84         template <typename Xs>
find_if_helperfind_if_impl85         static constexpr auto find_if_helper(Xs&&, hana::false_)
86         { return hana::nothing; }
87 
88         template <typename Xs>
find_if_helperfind_if_impl89         static constexpr auto find_if_helper(Xs&& xs, hana::true_)
90         { return hana::just(static_cast<Xs&&>(xs)[0]); }
91 
92         template <typename Xs, typename Pred>
applyfind_if_impl93         static constexpr auto apply(Xs&& xs, Pred&& pred) {
94             return find_if_helper(static_cast<Xs&&>(xs),
95                 hana::bool_c<decltype(
96                     static_cast<Pred&&>(pred)(static_cast<Xs&&>(xs)[0])
97                 )::value>
98             );
99         }
100     };
101 
102     namespace struct_detail {
103         template <typename X>
104         struct get_member {
105             X x;
106             template <typename Member>
operator ()struct_detail::get_member107             constexpr decltype(auto) operator()(Member&& member) && {
108                 return hana::second(static_cast<Member&&>(member))(
109                     static_cast<X&&>(x)
110                 );
111             }
112         };
113     }
114 
115     template <typename S>
116     struct find_if_impl<S, when<hana::Struct<S>::value>> {
117         template <typename X, typename Pred>
applyfind_if_impl118         static constexpr decltype(auto) apply(X&& x, Pred&& pred) {
119             return hana::transform(
120                 hana::find_if(hana::accessors<S>(),
121                     hana::compose(static_cast<Pred&&>(pred), hana::first)
122                 ),
123                 struct_detail::get_member<X>{static_cast<X&&>(x)}
124             );
125         }
126     };
127 BOOST_HANA_NAMESPACE_END
128 
129 #endif // !BOOST_HANA_FIND_IF_HPP
130