]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/hana/include/boost/hana/at_key.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / hana / include / boost / hana / at_key.hpp
1 /*!
2 @file
3 Defines `boost::hana::at_key`.
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_AT_KEY_HPP
11 #define BOOST_HANA_AT_KEY_HPP
12
13 #include <boost/hana/fwd/at_key.hpp>
14
15 #include <boost/hana/accessors.hpp>
16 #include <boost/hana/at.hpp>
17 #include <boost/hana/concept/searchable.hpp>
18 #include <boost/hana/concept/struct.hpp>
19 #include <boost/hana/config.hpp>
20 #include <boost/hana/core/dispatch.hpp>
21 #include <boost/hana/detail/decay.hpp>
22 #include <boost/hana/equal.hpp>
23 #include <boost/hana/find.hpp>
24 #include <boost/hana/find_if.hpp>
25 #include <boost/hana/first.hpp>
26 #include <boost/hana/functional/on.hpp>
27 #include <boost/hana/length.hpp>
28 #include <boost/hana/optional.hpp>
29 #include <boost/hana/second.hpp>
30
31 #include <cstddef>
32 #include <utility>
33
34
35 BOOST_HANA_NAMESPACE_BEGIN
36 //! @cond
37 template <typename Xs, typename Key>
38 constexpr decltype(auto) at_key_t::operator()(Xs&& xs, Key const& key) const {
39 using S = typename hana::tag_of<Xs>::type;
40 using AtKey = BOOST_HANA_DISPATCH_IF(at_key_impl<S>,
41 hana::Searchable<S>::value
42 );
43
44 #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
45 static_assert(hana::Searchable<S>::value,
46 "hana::at_key(xs, key) requires 'xs' to be Searchable");
47 #endif
48
49 return AtKey::apply(static_cast<Xs&&>(xs), key);
50 }
51 //! @endcond
52
53 template <typename S, bool condition>
54 struct at_key_impl<S, when<condition>> : default_ {
55 template <typename Xs, typename Key>
56 static constexpr auto apply(Xs&& xs, Key const& key) {
57 return hana::find(static_cast<Xs&&>(xs), key).value();
58 }
59 };
60
61 namespace at_key_detail {
62 template <typename T>
63 struct equal_to {
64 T const& t;
65 template <typename U>
66 constexpr auto operator()(U const& u) const {
67 return hana::equal(t, u);
68 }
69 };
70
71 //! @todo This causes an awful duplication of code with `find_if`.
72 template <typename Xs, typename Pred, std::size_t i, std::size_t N, bool Done>
73 struct advance_until;
74
75 template <typename Xs, typename Pred, std::size_t i, std::size_t N>
76 struct advance_until<Xs, Pred, i, N, false>
77 : advance_until<Xs, Pred, i + 1, N, static_cast<bool>(detail::decay<decltype(
78 std::declval<Pred>()(hana::at_c<i>(std::declval<Xs>()))
79 )>::type::value)>
80 { };
81
82 template <typename Xs, typename Pred, std::size_t N>
83 struct advance_until<Xs, Pred, N, N, false> {
84 template <typename Ys>
85 static constexpr auto apply(Ys&&) = delete;
86 };
87
88 template <typename Xs, typename Pred, std::size_t i, std::size_t N>
89 struct advance_until<Xs, Pred, i, N, true> {
90 template <typename Ys>
91 static constexpr decltype(auto) apply(Ys&& ys) {
92 return hana::at_c<i - 1>(static_cast<Ys&&>(ys));
93 }
94 };
95 }
96
97 template <typename S>
98 struct at_key_impl<S, when<hana::Sequence<S>::value>> {
99 template <typename Xs, typename Key>
100 static constexpr decltype(auto) apply(Xs&& xs, Key const&) {
101 constexpr std::size_t N = decltype(hana::length(xs))::value;
102 using Pred = at_key_detail::equal_to<Key>;
103 return at_key_detail::advance_until<Xs&&, Pred, 0, N, false>::apply(
104 static_cast<Xs&&>(xs)
105 );
106 }
107 };
108
109 template <typename S>
110 struct at_key_impl<S, when<hana::Struct<S>::value>> {
111 template <typename X, typename Key>
112 static constexpr decltype(auto) apply(X&& x, Key const& key) {
113 auto accessor = hana::second(*hana::find_if(hana::accessors<S>(),
114 hana::equal.to(key) ^hana::on^ hana::first
115 ));
116 return accessor(static_cast<X&&>(x));
117 }
118 };
119 BOOST_HANA_NAMESPACE_END
120
121 #endif // !BOOST_HANA_AT_KEY_HPP