]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/hana/example/misc/lambda_tuple.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / hana / example / misc / lambda_tuple.cpp
1 // Copyright Louis Dionne 2013-2017
2 // Distributed under the Boost Software License, Version 1.0.
3 // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
4
5 #include <boost/hana/at.hpp>
6 #include <boost/hana/bool.hpp>
7 #include <boost/hana/config.hpp>
8 #include <boost/hana/detail/variadic/at.hpp>
9 #include <boost/hana/detail/variadic/drop_into.hpp>
10 #include <boost/hana/detail/variadic/take.hpp>
11 #include <boost/hana/functional/always.hpp>
12 #include <boost/hana/functional/id.hpp>
13 #include <boost/hana/functional/on.hpp>
14 #include <boost/hana/fwd/append.hpp>
15 #include <boost/hana/fwd/at.hpp>
16 #include <boost/hana/fwd/concat.hpp>
17 #include <boost/hana/fwd/concept/sequence.hpp>
18 #include <boost/hana/fwd/core/make.hpp>
19 #include <boost/hana/fwd/drop_front.hpp>
20 #include <boost/hana/fwd/empty.hpp>
21 #include <boost/hana/fwd/front.hpp>
22 #include <boost/hana/fwd/prepend.hpp>
23 #include <boost/hana/fwd/take_front.hpp>
24 #include <boost/hana/fwd/transform.hpp>
25 #include <boost/hana/fwd/unpack.hpp>
26 #include <boost/hana/fwd/zip_shortest_with.hpp>
27 #include <boost/hana/integral_constant.hpp>
28 #include <boost/hana/is_empty.hpp>
29 #include <boost/hana/length.hpp>
30 #include <boost/hana/min.hpp>
31 #include <boost/hana/minimum.hpp>
32 #include <boost/hana/range.hpp>
33 #include <boost/hana/unpack.hpp>
34
35 #include <utility>
36 namespace hana = boost::hana;
37
38
39 // An interesting way of implementing tuple using lambda captures.
40
41 struct lambda_tuple_tag { };
42
43 template <typename Storage>
44 struct lambda_tuple_t {
45 explicit constexpr lambda_tuple_t(Storage&& s)
46 : storage(std::move(s))
47 { }
48
49 using hana_tag = lambda_tuple_tag;
50 Storage storage;
51 };
52
53 auto lambda_tuple = [](auto ...xs) {
54 auto storage = [=](auto f) -> decltype(auto) { return f(xs...); };
55 return lambda_tuple_t<decltype(storage)>{std::move(storage)};
56 };
57
58 namespace boost { namespace hana {
59 //////////////////////////////////////////////////////////////////////////
60 // Foldable
61 //////////////////////////////////////////////////////////////////////////
62 template <>
63 struct unpack_impl<lambda_tuple_tag> {
64 template <typename Xs, typename F>
65 static constexpr decltype(auto) apply(Xs&& xs, F&& f) {
66 return static_cast<Xs&&>(xs).storage(static_cast<F&&>(f));
67 }
68 };
69
70 //////////////////////////////////////////////////////////////////////////
71 // Functor
72 //////////////////////////////////////////////////////////////////////////
73 template <>
74 struct transform_impl<lambda_tuple_tag> {
75 template <typename Xs, typename F>
76 static constexpr decltype(auto) apply(Xs&& xs, F f) {
77 return static_cast<Xs&&>(xs).storage(
78 [f(std::move(f))](auto&& ...xs) -> decltype(auto) {
79 return lambda_tuple(f(static_cast<decltype(xs)&&>(xs))...);
80 }
81 );
82 }
83 };
84
85 //////////////////////////////////////////////////////////////////////////
86 // Iterable
87 //////////////////////////////////////////////////////////////////////////
88 template <>
89 struct front_impl<lambda_tuple_tag> {
90 template <typename Xs>
91 static constexpr decltype(auto) apply(Xs&& xs) {
92 return static_cast<Xs&&>(xs).storage(
93 [](auto&& x, auto&& ...) -> decltype(auto) {
94 return id(static_cast<decltype(x)&&>(x));
95 }
96 );
97 }
98 };
99
100 template <>
101 struct is_empty_impl<lambda_tuple_tag> {
102 template <typename Xs>
103 static constexpr decltype(auto) apply(Xs&& xs) {
104 return static_cast<Xs&&>(xs).storage(
105 [](auto const& ...xs) -> decltype(auto) {
106 return hana::bool_c<sizeof...(xs) == 0>;
107 }
108 );
109 }
110 };
111
112 template <>
113 struct at_impl<lambda_tuple_tag> {
114 template <typename Xs, typename Index>
115 static constexpr decltype(auto) apply(Xs&& xs, Index const&) {
116 return static_cast<Xs&&>(xs).storage(
117 detail::variadic::at<Index::value>
118 );
119 }
120 };
121
122 template <>
123 struct drop_front_impl<lambda_tuple_tag> {
124 template <typename Xs, typename N>
125 static constexpr decltype(auto) apply(Xs&& xs, N const& n) {
126 auto m = min(n, length(xs));
127 return static_cast<Xs&&>(xs).storage(
128 detail::variadic::drop_into<hana::value(m)>(lambda_tuple)
129 );
130 }
131 };
132
133 //////////////////////////////////////////////////////////////////////////
134 // MonadPlus
135 //////////////////////////////////////////////////////////////////////////
136 template <>
137 struct concat_impl<lambda_tuple_tag> {
138 template <typename Xs, typename Ys>
139 static constexpr decltype(auto) apply(Xs&& xs, Ys&& ys) {
140 return static_cast<Xs&&>(xs).storage(
141 [ys(static_cast<Ys&&>(ys))](auto&& ...xs) -> decltype(auto) {
142 return std::move(ys).storage(
143 // We can't initialize the capture with perfect
144 // forwarding since that's not supported by the
145 // language.
146 [=](auto&& ...ys) -> decltype(auto) {
147 return lambda_tuple(
148 std::move(xs)...,
149 static_cast<decltype(ys)&&>(ys)...
150 );
151 }
152 );
153 }
154 );
155 }
156 };
157
158 template <>
159 struct prepend_impl<lambda_tuple_tag> {
160 template <typename Xs, typename X>
161 static constexpr decltype(auto) apply(Xs&& xs, X&& x) {
162 return static_cast<Xs&&>(xs).storage(
163 [x(static_cast<X&&>(x))](auto&& ...xs) -> decltype(auto) {
164 return lambda_tuple(
165 std::move(x),
166 static_cast<decltype(xs)&&>(xs)...
167 );
168 }
169 );
170 }
171 };
172
173 template <>
174 struct append_impl<lambda_tuple_tag> {
175 template <typename Xs, typename X>
176 static constexpr decltype(auto) apply(Xs&& xs, X&& x) {
177 return static_cast<Xs&&>(xs).storage(
178 [x(static_cast<X&&>(x))](auto&& ...xs) -> decltype(auto) {
179 return lambda_tuple(
180 static_cast<decltype(xs)&&>(xs)...,
181 std::move(x)
182 );
183 }
184 );
185 }
186 };
187
188 template <>
189 struct empty_impl<lambda_tuple_tag> {
190 static BOOST_HANA_CONSTEXPR_LAMBDA decltype(auto) apply() {
191 return lambda_tuple();
192 }
193 };
194
195 //////////////////////////////////////////////////////////////////////////
196 // Sequence
197 //////////////////////////////////////////////////////////////////////////
198 template <>
199 struct Sequence<lambda_tuple_tag> {
200 static constexpr bool value = true;
201 };
202
203 template <>
204 struct take_front_impl<lambda_tuple_tag> {
205 template <typename Xs, typename N>
206 static constexpr decltype(auto) apply(Xs&& xs, N const& n) {
207 auto m = min(n, length(xs));
208 return static_cast<Xs&&>(xs).storage(
209 detail::variadic::take<decltype(m)::value>
210 )(lambda_tuple);
211 }
212 };
213
214 template <>
215 struct zip_shortest_with_impl<lambda_tuple_tag> {
216 template <typename F, typename ...Xss>
217 static constexpr auto apply(F f, Xss ...tuples) {
218 auto go = [=](auto index, auto ...nothing) {
219 return always(f)(nothing...)(at(tuples, index)...);
220 };
221 auto zip_length = minimum(lambda_tuple(length(tuples)...));
222 return unpack(make_range(size_c<0>, zip_length),
223 on(lambda_tuple, go)
224 );
225 }
226 };
227
228 //////////////////////////////////////////////////////////////////////////
229 // make
230 //////////////////////////////////////////////////////////////////////////
231 template <>
232 struct make_impl<lambda_tuple_tag> {
233 template <typename ...Xs>
234 static constexpr decltype(auto) apply(Xs&& ...xs) {
235 return lambda_tuple(static_cast<Xs&&>(xs)...);
236 }
237 };
238 }} // end namespace boost::hana
239
240
241 int main() {
242 auto xs = lambda_tuple(1, '2', 3.3);
243 static_assert(!decltype(hana::is_empty(xs))::value, "");
244 }