]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/hana/test/lazy.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / hana / test / lazy.cpp
1 // Copyright Louis Dionne 2013-2016
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/lazy.hpp>
6
7 #include <boost/hana/ap.hpp>
8 #include <boost/hana/assert.hpp>
9 #include <boost/hana/chain.hpp>
10 #include <boost/hana/concept/comparable.hpp>
11 #include <boost/hana/config.hpp>
12 #include <boost/hana/duplicate.hpp>
13 #include <boost/hana/equal.hpp>
14 #include <boost/hana/eval.hpp>
15 #include <boost/hana/extend.hpp>
16 #include <boost/hana/extract.hpp>
17 #include <boost/hana/flatten.hpp>
18 #include <boost/hana/functional/compose.hpp>
19 #include <boost/hana/lift.hpp>
20 #include <boost/hana/transform.hpp>
21 #include <boost/hana/tuple.hpp>
22
23 #include <laws/applicative.hpp>
24 #include <laws/base.hpp>
25 #include <laws/comonad.hpp>
26 #include <laws/functor.hpp>
27 #include <laws/monad.hpp>
28 #include <support/tracked.hpp>
29
30 #include <array>
31 #include <iostream>
32 namespace hana = boost::hana;
33 using hana::test::ct_eq;
34
35
36 namespace boost { namespace hana {
37 // We provide this instance for unit tests only because it is _so_ much
38 // more convenient, but this instance is too dangerous for general usage.
39 // See the documentation of `hana::lazy` for more info.
40 template <>
41 struct equal_impl<lazy_tag, lazy_tag> {
42 template <typename X, typename Y>
43 static constexpr auto apply(X x, Y y)
44 { return hana::equal(hana::eval(x), hana::eval(y)); }
45 };
46 }}
47
48 auto invalid = [](auto x)
49 { return x.this_function_must_not_be_instantiated; };
50
51
52 int main() {
53 hana::test::_injection<0> f{};
54
55 auto eqs = hana::make_tuple(
56 hana::make_lazy(ct_eq<0>{}),
57 hana::make_lazy(ct_eq<1>{}),
58 hana::make_lazy(ct_eq<2>{})
59 );
60 auto eq_elems = hana::make_tuple(ct_eq<0>{}, ct_eq<1>{}, ct_eq<1>{});
61 auto nested = hana::make_tuple(
62 hana::make_lazy(hana::make_lazy(ct_eq<0>{})),
63 hana::make_lazy(hana::make_lazy(ct_eq<1>{})),
64 hana::make_lazy(hana::make_lazy(ct_eq<2>{}))
65 );
66
67 //////////////////////////////////////////////////////////////////////////
68 // Lazy methods
69 //////////////////////////////////////////////////////////////////////////
70 {
71 // lazy
72 {
73 BOOST_HANA_CONSTANT_CHECK(hana::equal(
74 hana::make_lazy(f)(),
75 hana::make_lazy(f())
76 ));
77 BOOST_HANA_CONSTANT_CHECK(hana::equal(
78 hana::make_lazy(f)(ct_eq<0>{}),
79 hana::make_lazy(f(ct_eq<0>{}))
80 ));
81 BOOST_HANA_CONSTANT_CHECK(hana::equal(
82 hana::make_lazy(f)(ct_eq<0>{}, ct_eq<1>{}),
83 hana::make_lazy(f(ct_eq<0>{}, ct_eq<1>{}))
84 ));
85 BOOST_HANA_CONSTANT_CHECK(hana::equal(
86 hana::make_lazy(f)(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
87 hana::make_lazy(f(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}))
88 ));
89
90 // The function is not applied.
91 hana::make_lazy(invalid)();
92 hana::make_lazy(invalid)(ct_eq<0>{});
93 hana::make_lazy(invalid)(ct_eq<0>{}, ct_eq<1>{});
94 hana::make_lazy(invalid)(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{});
95 }
96
97 // eval
98 {
99 // With lazy expressions
100 BOOST_HANA_CONSTANT_CHECK(hana::equal(
101 hana::eval(hana::make_lazy(ct_eq<0>{})),
102 ct_eq<0>{}
103 ));
104 BOOST_HANA_CONSTANT_CHECK(hana::equal(
105 hana::eval(hana::make_lazy(ct_eq<1>{})),
106 ct_eq<1>{}
107 ));
108
109 BOOST_HANA_CONSTANT_CHECK(hana::equal(
110 hana::eval(hana::make_lazy(f)()),
111 f()
112 ));
113 BOOST_HANA_CONSTANT_CHECK(hana::equal(
114 hana::eval(hana::make_lazy(f)(ct_eq<3>{})),
115 f(ct_eq<3>{})
116 ));
117 BOOST_HANA_CONSTANT_CHECK(hana::equal(
118 hana::eval(hana::make_lazy(f)(ct_eq<3>{}, ct_eq<4>{})),
119 f(ct_eq<3>{}, ct_eq<4>{})
120 ));
121
122 // Should call a nullary function
123 BOOST_HANA_CONSTANT_CHECK(hana::equal(
124 hana::eval([]{ return ct_eq<3>{}; }),
125 ct_eq<3>{}
126 ));
127
128 // Should call a unary function with hana::id.
129 BOOST_HANA_CONSTANT_CHECK(hana::equal(
130 hana::eval([](auto _) { return _(ct_eq<3>{}); }),
131 ct_eq<3>{}
132 ));
133
134 // For overloaded function objects that are both nullary and unary,
135 // the nullary overload should be preferred.
136 BOOST_HANA_CONSTANT_CHECK(hana::equal(
137 hana::eval(f),
138 f()
139 ));
140 }
141
142 // Make sure this does not move from a destroyed object, as that
143 // used to be the case.
144 {
145 auto x = hana::flatten(hana::make_lazy(hana::make_lazy(Tracked{1})));
146 auto z = hana::eval(x); (void)z;
147 }
148
149 // In some cases where a type has a constructor that is way too
150 // general, copying a lazy value holding an object of that type
151 // could trigger the instantiation of that constructor. If that
152 // constructor was ill-formed, the compilation would fail. We
153 // make sure this does not happen.
154 {
155 {
156 auto expr = hana::make_lazy(hana::test::trap_construct{});
157 auto implicit_copy = expr; (void)implicit_copy;
158 decltype(expr) explicit_copy(expr); (void)explicit_copy;
159 }
160
161 {
162 auto expr = hana::make_lazy(hana::test::trap_construct{})();
163 auto implicit_copy = expr; (void)implicit_copy;
164 decltype(expr) explicit_copy(expr); (void)explicit_copy;
165 }
166 }
167 }
168
169 //////////////////////////////////////////////////////////////////////////
170 // Functor
171 //////////////////////////////////////////////////////////////////////////
172 {
173 // transform
174 {
175 BOOST_HANA_CONSTANT_CHECK(hana::equal(
176 hana::transform(hana::make_lazy(ct_eq<0>{}), f),
177 hana::make_lazy(f(ct_eq<0>{}))
178 ));
179 }
180
181 // laws
182 hana::test::TestFunctor<hana::lazy_tag>{eqs, eq_elems};
183 }
184
185 //////////////////////////////////////////////////////////////////////////
186 // Applicative
187 //////////////////////////////////////////////////////////////////////////
188 {
189 // ap
190 {
191 BOOST_HANA_CONSTANT_CHECK(hana::equal(
192 hana::ap(hana::make_lazy(f), hana::make_lazy(ct_eq<0>{})),
193 hana::make_lazy(f(ct_eq<0>{}))
194 ));
195 BOOST_HANA_CONSTANT_CHECK(hana::equal(
196 hana::ap(hana::make_lazy(f), hana::make_lazy(ct_eq<0>{}), hana::make_lazy(ct_eq<1>{})),
197 hana::make_lazy(f(ct_eq<0>{}, ct_eq<1>{}))
198 ));
199 BOOST_HANA_CONSTANT_CHECK(hana::equal(
200 hana::ap(hana::make_lazy(f), hana::make_lazy(ct_eq<0>{}), hana::make_lazy(ct_eq<1>{}), hana::make_lazy(ct_eq<2>{})),
201 hana::make_lazy(f(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}))
202 ));
203
204 // The function is not applied.
205 hana::ap(hana::make_lazy(invalid), hana::make_lazy(ct_eq<0>{}));
206 hana::ap(hana::make_lazy(invalid), hana::make_lazy(ct_eq<0>{}), hana::make_lazy(ct_eq<1>{}));
207 hana::ap(hana::make_lazy(invalid), hana::make_lazy(ct_eq<0>{}), hana::make_lazy(ct_eq<1>{}), hana::make_lazy(ct_eq<2>{}));
208 }
209
210 // lift
211 {
212 BOOST_HANA_CONSTANT_CHECK(hana::equal(
213 hana::lift<hana::lazy_tag>(ct_eq<0>{}),
214 hana::make_lazy(ct_eq<0>{})
215 ));
216 BOOST_HANA_CONSTANT_CHECK(hana::equal(
217 hana::lift<hana::lazy_tag>(ct_eq<1>{}),
218 hana::make_lazy(ct_eq<1>{})
219 ));
220 }
221
222 // laws
223 hana::test::TestApplicative<hana::lazy_tag>{eqs};
224 }
225
226 //////////////////////////////////////////////////////////////////////////
227 // Monad
228 //////////////////////////////////////////////////////////////////////////
229 {
230 auto f_ = hana::compose(hana::make_lazy, f);
231
232 // chain
233 {
234 BOOST_HANA_CONSTANT_CHECK(hana::equal(
235 hana::chain(hana::make_lazy(ct_eq<0>{}), f_),
236 f_(ct_eq<0>{})
237 ));
238 BOOST_HANA_CONSTANT_CHECK(hana::equal(
239 hana::chain(hana::make_lazy(ct_eq<1>{}), f_),
240 f_(ct_eq<1>{})
241 ));
242
243 BOOST_HANA_CONSTANT_CHECK(hana::equal(
244 hana::make_lazy(ct_eq<1>{}) | f_,
245 f_(ct_eq<1>{})
246 ));
247 }
248
249 // flatten
250 {
251 BOOST_HANA_CONSTANT_CHECK(hana::equal(
252 hana::flatten(hana::make_lazy(hana::make_lazy(ct_eq<0>{}))),
253 hana::make_lazy(ct_eq<0>{})
254 ));
255 BOOST_HANA_CONSTANT_CHECK(hana::equal(
256 hana::flatten(hana::make_lazy(hana::make_lazy(ct_eq<1>{}))),
257 hana::make_lazy(ct_eq<1>{})
258 ));
259 BOOST_HANA_CONSTANT_CHECK(hana::equal(
260 hana::flatten(hana::make_lazy(hana::make_lazy(hana::make_lazy(ct_eq<1>{})))),
261 hana::make_lazy(hana::make_lazy(ct_eq<1>{}))
262 ));
263 }
264
265 // laws
266 hana::test::TestMonad<hana::lazy_tag>{eqs, nested};
267 }
268
269 //////////////////////////////////////////////////////////////////////////
270 // Comonad
271 //////////////////////////////////////////////////////////////////////////
272 {
273 // extract
274 {
275 BOOST_HANA_CONSTANT_CHECK(hana::equal(
276 hana::extract(hana::make_lazy(ct_eq<4>{})),
277 ct_eq<4>{}
278 ));
279 }
280
281 // duplicate
282 {
283 BOOST_HANA_CONSTANT_CHECK(hana::equal(
284 hana::duplicate(hana::make_lazy(ct_eq<4>{})),
285 hana::make_lazy(hana::make_lazy(ct_eq<4>{}))
286 ));
287 }
288
289 // extend
290 {
291 BOOST_HANA_CONSTANT_CHECK(hana::equal(
292 hana::extend(hana::make_lazy(ct_eq<4>{}), f),
293 hana::make_lazy(f(hana::make_lazy(ct_eq<4>{})))
294 ));
295 }
296
297 // laws
298 hana::test::TestComonad<hana::lazy_tag>{eqs};
299 }
300
301 //////////////////////////////////////////////////////////////////////////
302 // Make sure the monadic chain is evaluated in the right order.
303 //////////////////////////////////////////////////////////////////////////
304 {
305 std::array<bool, 3> executed = {{false, false, false}};
306 int dummy = 0;
307
308 std::cout << "creating the monadic chain...\n";
309 auto chain = hana::make_lazy(dummy)
310 | [&](int dummy) {
311 std::cout << "executing the first computation...\n";
312 executed[0] = true;
313 BOOST_HANA_RUNTIME_CHECK(
314 executed == std::array<bool, 3>{{true, false, false}}
315 );
316 return hana::make_lazy(dummy);
317 }
318 | [&](int dummy) {
319 std::cout << "executing the second computation...\n";
320 executed[1] = true;
321 BOOST_HANA_RUNTIME_CHECK(
322 executed == std::array<bool, 3>{{true, true, false}}
323 );
324 return hana::make_lazy(dummy);
325 }
326 | [&](int dummy) {
327 std::cout << "executing the third computation...\n";
328 executed[2] = true;
329 BOOST_HANA_RUNTIME_CHECK(
330 executed == std::array<bool, 3>{{true, true, true}}
331 );
332 return hana::make_lazy(dummy);
333 };
334
335 BOOST_HANA_RUNTIME_CHECK(
336 executed == std::array<bool, 3>{{false, false, false}}
337 );
338
339 std::cout << "evaluating the chain...\n";
340 hana::eval(chain);
341 }
342 }