]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/hana/example/tutorial/appendix_mpl.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / hana / example / tutorial / appendix_mpl.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.hpp>
6 #include <boost/hana/ext/boost/mpl.hpp>
7 #include <boost/hana/ext/std.hpp>
8
9 #include <boost/mpl/lambda.hpp>
10 #include <boost/mpl/placeholders.hpp>
11 #include <boost/mpl/quote.hpp>
12
13 #include <iostream>
14 #include <type_traits>
15 namespace hana = boost::hana;
16 namespace mpl = boost::mpl;
17
18
19 namespace hpl {
20 //////////////////////////////////////////////////////////////////////////////
21 // Utilities
22 //////////////////////////////////////////////////////////////////////////////
23 namespace detail {
24 template <typename Pred>
25 constexpr auto mpl_predicate = hana::integral(hana::metafunction_class<
26 typename mpl::lambda<Pred>::type
27 >);
28
29 template <typename F>
30 constexpr auto mpl_metafunction = hana::metafunction_class<
31 typename mpl::lambda<F>::type
32 >;
33 }
34
35 //////////////////////////////////////////////////////////////////////////////
36 // integral_c
37 //////////////////////////////////////////////////////////////////////////////
38 template <typename T, T v>
39 using integral_c = std::integral_constant<T, v>;
40
41 template <int i>
42 using int_ = integral_c<int, i>;
43
44 template <long i>
45 using long_ = integral_c<long, i>;
46
47 template <bool b>
48 using bool_ = integral_c<bool, b>;
49
50 using true_ = bool_<true>;
51 using false_ = bool_<false>;
52
53
54 //////////////////////////////////////////////////////////////////////////////
55 // Sequences, compile-time integers & al
56 //
57 // Differences with the MPL:
58 // 1. `pair<...>::first` and `pair<...>::second` won't work;
59 // use `first<pair<...>>` instead
60 //////////////////////////////////////////////////////////////////////////////
61 template <typename ...T>
62 using vector = hana::tuple<hana::type<T>...>;
63
64 template <typename T, T ...v>
65 using vector_c = hana::tuple<hana::integral_constant<T, v>...>;
66
67 template <typename T, T from, T to>
68 using range_c = decltype(hana::range_c<T, from, to>);
69
70
71 template <typename T, typename U>
72 using pair = hana::pair<hana::type<T>, hana::type<U>>;
73
74 template <typename P>
75 struct first : decltype(+hana::first(P{})) { };
76
77 template <typename P>
78 struct second : decltype(+hana::second(P{})) { };
79
80
81 //////////////////////////////////////////////////////////////////////////////
82 // Miscellaneous metafunctions
83 //////////////////////////////////////////////////////////////////////////////
84 template <typename C1, typename C2>
85 struct equal_to
86 : bool_<C1::value == C2::value>
87 { };
88
89 template <typename C1, typename C2>
90 struct less
91 : bool_<(C1::value < C2::value)>
92 { };
93
94 template <typename C1, typename C2>
95 struct greater
96 : bool_<(C1::value > C2::value)>
97 { };
98
99 template <typename N>
100 struct next
101 : integral_c<typename N::value_type, N::value + 1>
102 { };
103
104 //////////////////////////////////////////////////////////////////////////////
105 // Intrinsics
106 //
107 // Differences with the MPL:
108 // 1. `at` does not work for associative sequences; use `find` instead.
109 // 2. `begin`, `end`, `clear`, `erase`, `erase_key`, `insert`, `insert_range`,
110 // `is_sequence`, `key_type`, `order`, `sequence_tag`, `value_type`: not implemented
111 //////////////////////////////////////////////////////////////////////////////
112 template <typename Sequence, typename N>
113 struct at
114 : decltype(hana::at(Sequence{}, N{}))
115 { };
116
117 template <typename Sequence, long n>
118 using at_c = at<Sequence, long_<n>>;
119
120 template <typename Sequence>
121 struct back
122 : decltype(+hana::back(Sequence{}))
123 { };
124
125 template <typename Sequence>
126 struct empty
127 : decltype(hana::is_empty(Sequence{}))
128 { };
129
130 template <typename Sequence>
131 struct front
132 : decltype(+hana::front(Sequence{}))
133 { };
134
135 template <typename Sequence>
136 struct pop_back {
137 using type = decltype(hana::drop_back(
138 hana::to_tuple(Sequence{}), hana::size_c<1>
139 ));
140 };
141
142 template <typename Sequence>
143 struct pop_front {
144 using type = decltype(hana::drop_front(Sequence{}));
145 };
146
147 template <typename Sequence, typename T>
148 struct push_back {
149 using type = decltype(hana::append(Sequence{}, hana::type_c<T>));
150 };
151
152 template <typename Sequence, typename T>
153 struct push_front {
154 using type = decltype(hana::prepend(Sequence{}, hana::type_c<T>));
155 };
156
157 template <typename Sequence>
158 struct size
159 : decltype(hana::length(Sequence{}))
160 { };
161
162 //////////////////////////////////////////////////////////////////////////////
163 // Iteration algorithms
164 //
165 // Differences with the MPL:
166 // 1. reverse_fold:
167 // Does not take an optional additional ForwardOp argument.
168 //
169 // 2. iter_fold, reverse_iter_fold:
170 // Not implemented because we don't use iterators
171 //////////////////////////////////////////////////////////////////////////////
172 template <typename Sequence, typename State, typename F>
173 struct fold
174 : decltype(hana::fold(
175 Sequence{}, hana::type_c<State>, detail::mpl_metafunction<F>
176 ))
177 { };
178
179 template <typename Sequence, typename State, typename F>
180 struct reverse_fold
181 : decltype(hana::reverse_fold(
182 Sequence{}, hana::type_c<State>, detail::mpl_metafunction<F>
183 ))
184 { };
185
186 template <typename Sequence, typename State, typename F>
187 using accumulate = fold<Sequence, State, F>;
188
189 //////////////////////////////////////////////////////////////////////////////
190 // Query algorithms
191 //
192 // Differences with the MPL:
193 // 1. find_if and find:
194 // Instead of returning an iterator, they either have a nested `::type`
195 // alias to the answer, or they have no nested `::type` at all, which
196 // makes them SFINAE-friendly.
197 //
198 // 2. lower_bound, upper_bound:
199 // Not implemented.
200 //
201 // 3. {min,max}_element:
202 // Not returning an iterator, and also won't work on empty sequences.
203 //////////////////////////////////////////////////////////////////////////////
204 template <typename Sequence, typename Pred>
205 struct find_if
206 : decltype(hana::find_if(Sequence{}, detail::mpl_predicate<Pred>))
207 { };
208
209 template <typename Sequence, typename T>
210 struct find
211 : decltype(hana::find(Sequence{}, hana::type_c<T>))
212 { };
213
214 template <typename Sequence, typename T>
215 struct contains
216 : decltype(hana::contains(Sequence{}, hana::type_c<T>))
217 { };
218
219 template <typename Sequence, typename T>
220 struct count
221 : decltype(hana::count(Sequence{}, hana::type_c<T>))
222 { };
223
224 template <typename Sequence, typename Pred>
225 struct count_if
226 : decltype(hana::count_if(Sequence{}, detail::mpl_predicate<Pred>))
227 { };
228
229 template <typename Sequence, typename Pred = mpl::quote2<less>>
230 struct min_element
231 : decltype(hana::minimum(Sequence{}, detail::mpl_predicate<Pred>))
232 { };
233
234 template <typename Sequence, typename Pred = mpl::quote2<less>>
235 struct max_element
236 : decltype(hana::maximum(Sequence{}, detail::mpl_predicate<Pred>))
237 { };
238
239 template <typename S1, typename S2, typename Pred = mpl::quote2<std::is_same>>
240 struct equal
241 : decltype( // inefficient but whatever
242 hana::length(S1{}) == hana::length(S2{}) &&
243 hana::all(hana::zip_shortest_with(detail::mpl_predicate<Pred>,
244 hana::to_tuple(S1{}),
245 hana::to_tuple(S2{})))
246 )
247 { };
248
249 //////////////////////////////////////////////////////////////////////////////
250 // Transformation algorithms
251 //
252 // Differences from the MPL:
253 // 1. The algorithms do not accept an optional inserter, and they always
254 // return a `vector`.
255 // 2. stable_partition: not implemented
256 // 3. All the reverse_* algorithms are not implemented.
257 //////////////////////////////////////////////////////////////////////////////
258 template <typename Sequence>
259 struct copy {
260 using type = decltype(hana::to_tuple(Sequence{}));
261 };
262
263 template <typename Sequence, typename Pred>
264 struct copy_if {
265 using type = decltype(hana::filter(
266 hana::to_tuple(Sequence{}),
267 detail::mpl_predicate<Pred>
268 ));
269 };
270
271 template <typename Sequence, typename Sequence_or_Op, typename = void>
272 struct transform;
273
274 template <typename Sequence, typename Op>
275 struct transform<Sequence, Op> {
276 using type = decltype(hana::transform(
277 hana::to_tuple(Sequence{}), detail::mpl_metafunction<Op>
278 ));
279 };
280
281 template <typename S1, typename S2, typename Op>
282 struct transform {
283 using type = decltype(hana::zip_with(
284 detail::mpl_metafunction<Op>,
285 hana::to_tuple(S1{}),
286 hana::to_tuple(S2{})
287 ));
288 };
289
290 template <typename Sequence, typename OldType, typename NewType>
291 struct replace {
292 using type = decltype(hana::replace(
293 hana::to_tuple(Sequence{}),
294 hana::type_c<OldType>,
295 hana::type_c<NewType>
296 ));
297 };
298
299 template <typename Sequence, typename Pred, typename NewType>
300 struct replace_if {
301 using type = decltype(hana::replace_if(
302 hana::to_tuple(Sequence{}),
303 detail::mpl_predicate<Pred>,
304 hana::type_c<NewType>
305 ));
306 };
307
308 template <typename Sequence, typename T>
309 struct remove {
310 using type = decltype(hana::filter(
311 hana::to_tuple(Sequence{}),
312 hana::not_equal.to(hana::type_c<T>)
313 ));
314 };
315
316 template <typename Sequence, typename Pred>
317 struct remove_if {
318 using type = decltype(hana::filter(
319 hana::to_tuple(Sequence{}),
320 hana::compose(hana::not_, detail::mpl_predicate<Pred>)
321 ));
322 };
323
324 template <typename Sequence, typename Pred>
325 struct unique {
326 using type = decltype(hana::unique(
327 hana::to_tuple(Sequence{}),
328 detail::mpl_predicate<Pred>
329 ));
330 };
331
332 template <typename Sequence, typename Pred>
333 struct partition {
334 using hana_pair = decltype(hana::partition(
335 hana::to_tuple(Sequence{}),
336 detail::mpl_predicate<Pred>
337 ));
338 using type = pair<
339 decltype(hana::first(hana_pair{})),
340 decltype(hana::second(hana_pair{}))
341 >;
342 };
343
344 template <typename Sequence, typename Pred = mpl::quote2<less>>
345 struct sort {
346 using type = decltype(hana::sort(
347 hana::to_tuple(Sequence{}), detail::mpl_predicate<Pred>
348 ));
349 };
350
351 template <typename Sequence>
352 struct reverse {
353 using type = decltype(hana::reverse(hana::to_tuple(Sequence{})));
354 };
355
356
357 //////////////////////////////////////////////////////////////////////////////
358 // Runtime algorithms
359 //////////////////////////////////////////////////////////////////////////////
360 template <typename Sequence, typename F>
361 void for_each(F f) {
362 hana::for_each(Sequence{}, [&f](auto t) {
363 f(typename decltype(t)::type{});
364 });
365 }
366
367 template <typename Sequence, typename TransformOp, typename F>
368 void for_each(F f) {
369 for_each<typename transform<Sequence, TransformOp>::type>(f);
370 }
371
372 } // end namespace hpl
373
374
375 template <typename N>
376 struct is_odd
377 : hpl::bool_<(N::value % 2)>
378 { };
379
380
381 int main() {
382 using namespace hpl;
383
384 //////////////////////////////////////////////////////////////////////////////
385 // Misc
386 //////////////////////////////////////////////////////////////////////////////
387
388 // pair
389 {
390 static_assert(std::is_same<first<pair<int, float>>::type, int>{}, "");
391 static_assert(std::is_same<second<pair<int, float>>::type, float>{}, "");
392 }
393
394 //////////////////////////////////////////////////////////////////////////////
395 // Intrinsics
396 //////////////////////////////////////////////////////////////////////////////
397
398 // at
399 {
400 using range = range_c<long,10,50>;
401 static_assert(at<range, int_<0>>::value == 10, "");
402 static_assert(at<range, int_<10>>::value == 20, "");
403 static_assert(at<range, int_<40>>::value == 50, "");
404 }
405
406 // at_c
407 {
408 using range = range_c<long, 10, 50>;
409 static_assert(at_c<range, 0>::value == 10, "");
410 static_assert(at_c<range, 10>::value == 20, "");
411 static_assert(at_c<range, 40>::value == 50, "");
412 }
413
414 // back
415 {
416 using range1 = range_c<int,0,1>;
417 using range2 = range_c<int,0,10>;
418 using range3 = range_c<int,-10,0>;
419 using types = vector<int, char, float>;
420 static_assert(back<range1>::value == 0, "");
421 static_assert(back<range2>::value == 9, "");
422 static_assert(back<range3>::value == -1, "");
423 static_assert(std::is_same<back<types>::type, float>{}, "");
424 }
425
426 // empty
427 {
428 using empty_range = range_c<int,0,0>;
429 using types = vector<long,float,double>;
430 static_assert(empty<empty_range>{}, "");
431 static_assert(!empty<types>{}, "");
432 }
433
434 // front
435 {
436 using types1 = vector<long>;
437 using types2 = vector<int,long>;
438 using types3 = vector<char,int,long>;
439 static_assert(std::is_same<front<types1>::type, long>{}, "");
440 static_assert(std::is_same<front<types2>::type, int>{}, "");
441 static_assert(std::is_same<front<types3>::type, char>{}, "");
442 }
443
444 // pop_back
445 {
446 using types1 = vector<long>;
447 using types2 = vector<long,int>;
448 using types3 = vector<long,int,char>;
449
450
451 using result1 = pop_back<types1>::type;
452 using result2 = pop_back<types2>::type;
453 using result3 = pop_back<types3>::type;
454
455 static_assert(size<result1>::value == 0, "");
456 static_assert(size<result2>::value == 1, "");
457 static_assert(size<result3>::value == 2, "");
458
459 static_assert(std::is_same< back<result2>::type, long>{}, "");
460 static_assert(std::is_same< back<result3>::type, int>{}, "");
461 }
462
463 // pop_front
464 {
465 using types1 = vector<long>;
466 using types2 = vector<int,long>;
467 using types3 = vector<char,int,long>;
468
469 using result1 = pop_front<types1>::type;
470 using result2 = pop_front<types2>::type;
471 using result3 = pop_front<types3>::type;
472
473 static_assert(size<result1>::value == 0, "");
474 static_assert(size<result2>::value == 1, "");
475 static_assert(size<result3>::value == 2, "");
476
477 static_assert(std::is_same<front<result2>::type, long>{}, "");
478 static_assert(std::is_same<front<result3>::type, int>{}, "");
479 }
480
481 // push_back
482 {
483 using bools = vector_c<bool,false,false,false,true,true,true,false,false>;
484 using message = push_back<bools, false_>::type;
485 static_assert(back<message>::type::value == false, "");
486 static_assert(count_if<message, equal_to<mpl::_1, false_>>{} == 6u, "");
487 }
488
489 // push_front
490 {
491 using v = vector_c<int,1,2,3,5,8,13,21>;
492 static_assert(size<v>{} == 7u, "");
493
494 using fibonacci = push_front<v, int_<1>>::type;
495 static_assert(size<fibonacci>{} == 8u, "");
496
497 static_assert(equal<
498 fibonacci,
499 vector_c<int,1,1,2,3,5,8,13,21>,
500 equal_to<mpl::_, mpl::_>
501 >{}, "");
502 }
503
504 // size
505 {
506 using empty_list = vector<>;
507 using numbers = vector_c<int,0,1,2,3,4,5>;
508 using more_numbers = range_c<int,0,100>;
509
510 static_assert(size<empty_list>{} == 0u, "");
511 static_assert(size<numbers>{} == 6u, "");
512 static_assert(size<more_numbers>{} == 100u, "");
513 }
514
515
516 //////////////////////////////////////////////////////////////////////////////
517 // Iteration algorithms
518 //////////////////////////////////////////////////////////////////////////////
519
520 // fold
521 {
522 using types = vector<long,float,short,double,float,long,long double>;
523 using number_of_floats = fold<types, int_<0>,
524 mpl::if_<std::is_floating_point<mpl::_2>,
525 next<mpl::_1>,
526 mpl::_1
527 >
528 >::type;
529 static_assert(number_of_floats{} == 4, "");
530 }
531
532 // reverse_fold
533 {
534 using numbers = vector_c<int,5,-1,0,-7,-2,0,-5,4>;
535 using negatives = vector_c<int,-1,-7,-2,-5>;
536 using result = reverse_fold<numbers, vector_c<int>,
537 mpl::if_<less<mpl::_2, int_<0>>,
538 push_front<mpl::_1, mpl::_2>,
539 mpl::_1
540 >
541 >::type;
542 static_assert(equal<negatives, result>{}, "");
543 }
544
545 //////////////////////////////////////////////////////////////////////////////
546 // Query algorithms
547 //////////////////////////////////////////////////////////////////////////////
548
549 // find_if
550 {
551 using types = vector<char,int,unsigned,long,unsigned long>;
552 using found = find_if<types, std::is_same<mpl::_1, unsigned>>::type;
553 static_assert(std::is_same<found, unsigned>{}, "");
554 }
555
556 // find
557 {
558 using types = vector<char,int,unsigned,long,unsigned long>;
559 static_assert(std::is_same<find<types, unsigned>::type, unsigned>{}, "");
560 }
561
562 // contains
563 {
564 using types = vector<char,int,unsigned,long,unsigned long>;
565 static_assert(!contains<types, bool>{}, "");
566 }
567
568 // count
569 {
570 using types = vector<int,char,long,short,char,short,double,long>;
571 static_assert(count<types, short>{} == 2u, "");
572 }
573
574 // count_if
575 {
576 using types = vector<int,char,long,short,char,long,double,long>;
577 static_assert(count_if<types, std::is_floating_point<mpl::_>>{} == 1u, "");
578 static_assert(count_if<types, std::is_same<mpl::_, char>>{} == 2u, "");
579 static_assert(count_if<types, std::is_same<mpl::_, void>>{} == 0u, "");
580 }
581
582 // min_element (MPL's example is completely broken)
583 {
584 }
585
586 // max_element (MPL's example is completely broken)
587 {
588 }
589
590 // equal
591 {
592 using s1 = vector<char,int,unsigned,long,unsigned long>;
593 using s2 = vector<char,int,unsigned,long>;
594 static_assert(!equal<s1,s2>{}, "");
595 }
596
597
598 //////////////////////////////////////////////////////////////////////////////
599 // Transformaton algorithms
600 //////////////////////////////////////////////////////////////////////////////
601 // copy
602 {
603 using numbers = vector_c<int,10, 11, 12, 13, 14, 15, 16, 17, 18, 19>;
604 using result = copy<range_c<int, 10, 20>>::type;
605 static_assert(size<result>{} == 10u, "");
606 static_assert(equal<result, numbers, mpl::quote2<equal_to>>{}, "");
607 }
608
609 // copy_if
610 {
611 using result = copy_if<range_c<int, 0, 10>, less<mpl::_1, int_<5>>>::type;
612 static_assert(size<result>{} == 5u, "");
613 static_assert(equal<result, range_c<int, 0, 5>>{}, "");
614 }
615
616 // transform
617 {
618 using types = vector<char,short,int,long,float,double>;
619 using pointers = vector<char*,short*,int*,long*,float*,double*>;
620 using result = transform<types,std::add_pointer<mpl::_1>>::type;
621 static_assert(equal<result, pointers>{}, "");
622 }
623
624 // replace
625 {
626 using types = vector<int,float,char,float,float,double>;
627 using expected = vector<int,double,char,double,double,double>;
628 using result = replace< types,float,double >::type;
629 static_assert(equal<result, expected>{}, "");
630 }
631
632 // replace_if
633 {
634 using numbers = vector_c<int,1,4,5,2,7,5,3,5>;
635 using expected = vector_c<int,1,4,0,2,0,0,3,0>;
636 using result = replace_if<numbers, greater<mpl::_, int_<4>>, int_<0>>::type;
637 static_assert(equal<result, expected, mpl::quote2<equal_to>>{}, "");
638 }
639
640 // remove
641 {
642 using types = vector<int,float,char,float,float,double>;
643 using result = hpl::remove<types, float>::type;
644 static_assert(equal<result, vector<int, char, double>>{}, "");
645 }
646
647 // remove_if
648 {
649 using numbers = vector_c<int,1,4,5,2,7,5,3,5>;
650 using result = remove_if<numbers, greater<mpl::_, int_<4> > >::type;
651 static_assert(equal<result, vector_c<int,1,4,2,3>, mpl::quote2<equal_to>>{}, "");
652 }
653
654 // unique
655 {
656 using types = vector<int,float,float,char,int,int,int,double>;
657 using expected = vector<int,float,char,int,double>;
658 using result = unique<types, std::is_same<mpl::_1, mpl::_2>>::type;
659 static_assert(equal<result, expected>{}, "");
660 }
661
662 // partition
663 {
664 using r = partition<range_c<int,0,10>, is_odd<mpl::_1>>::type;
665 static_assert(equal<first<r>::type, vector_c<int,1,3,5,7,9>>{}, "");
666 static_assert(equal<second<r>::type, vector_c<int,0,2,4,6,8>>{}, "");
667 }
668
669 // sort
670 {
671 using numbers = vector_c<int,3,4,0,-5,8,-1,7>;
672 using expected = vector_c<int,-5,-1,0,3,4,7,8>;
673 using result = sort<numbers>::type;
674 static_assert(equal<result, expected, equal_to<mpl::_, mpl::_>>{}, "");
675 }
676
677 // reverse
678 {
679 using numbers = vector_c<int,9,8,7,6,5,4,3,2,1,0>;
680 using result = reverse<numbers>::type;
681 static_assert(equal<result, range_c<int,0,10>>{}, "");
682 }
683
684 //////////////////////////////////////////////////////////////////////////////
685 // Runtime algorithms
686 //////////////////////////////////////////////////////////////////////////////
687
688 // for_each
689 {
690 auto value_printer = [](auto x) {
691 std::cout << x << '\n';
692 };
693
694 for_each<range_c<int, 0, 10> >(value_printer);
695 }
696
697 }