]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/hana/example/tutorial/appendix_mpl.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / hana / example / tutorial / appendix_mpl.cpp
CommitLineData
b32b8144 1// Copyright Louis Dionne 2013-2017
7c673cae
FG
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>
15namespace hana = boost::hana;
16namespace mpl = boost::mpl;
17
18
19namespace hpl {
20//////////////////////////////////////////////////////////////////////////////
21// Utilities
22//////////////////////////////////////////////////////////////////////////////
23namespace 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//////////////////////////////////////////////////////////////////////////////
38template <typename T, T v>
39using integral_c = std::integral_constant<T, v>;
40
41template <int i>
42using int_ = integral_c<int, i>;
43
44template <long i>
45using long_ = integral_c<long, i>;
46
47template <bool b>
48using bool_ = integral_c<bool, b>;
49
50using true_ = bool_<true>;
51using 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//////////////////////////////////////////////////////////////////////////////
61template <typename ...T>
62using vector = hana::tuple<hana::type<T>...>;
63
64template <typename T, T ...v>
65using vector_c = hana::tuple<hana::integral_constant<T, v>...>;
66
67template <typename T, T from, T to>
68using range_c = decltype(hana::range_c<T, from, to>);
69
70
71template <typename T, typename U>
72using pair = hana::pair<hana::type<T>, hana::type<U>>;
73
74template <typename P>
75struct first : decltype(+hana::first(P{})) { };
76
77template <typename P>
78struct second : decltype(+hana::second(P{})) { };
79
80
81//////////////////////////////////////////////////////////////////////////////
82// Miscellaneous metafunctions
83//////////////////////////////////////////////////////////////////////////////
84template <typename C1, typename C2>
85struct equal_to
86 : bool_<C1::value == C2::value>
87{ };
88
89template <typename C1, typename C2>
90struct less
91 : bool_<(C1::value < C2::value)>
92{ };
93
94template <typename C1, typename C2>
95struct greater
96 : bool_<(C1::value > C2::value)>
97{ };
98
99template <typename N>
100struct 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//////////////////////////////////////////////////////////////////////////////
112template <typename Sequence, typename N>
113struct at
114 : decltype(hana::at(Sequence{}, N{}))
115{ };
116
117template <typename Sequence, long n>
118using at_c = at<Sequence, long_<n>>;
119
120template <typename Sequence>
121struct back
122 : decltype(+hana::back(Sequence{}))
123{ };
124
125template <typename Sequence>
126struct empty
127 : decltype(hana::is_empty(Sequence{}))
128{ };
129
130template <typename Sequence>
131struct front
132 : decltype(+hana::front(Sequence{}))
133{ };
134
135template <typename Sequence>
136struct pop_back {
137 using type = decltype(hana::drop_back(
138 hana::to_tuple(Sequence{}), hana::size_c<1>
139 ));
140};
141
142template <typename Sequence>
143struct pop_front {
144 using type = decltype(hana::drop_front(Sequence{}));
145};
146
147template <typename Sequence, typename T>
148struct push_back {
149 using type = decltype(hana::append(Sequence{}, hana::type_c<T>));
150};
151
152template <typename Sequence, typename T>
153struct push_front {
154 using type = decltype(hana::prepend(Sequence{}, hana::type_c<T>));
155};
156
157template <typename Sequence>
158struct 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//////////////////////////////////////////////////////////////////////////////
172template <typename Sequence, typename State, typename F>
173struct fold
174 : decltype(hana::fold(
175 Sequence{}, hana::type_c<State>, detail::mpl_metafunction<F>
176 ))
177{ };
178
179template <typename Sequence, typename State, typename F>
180struct reverse_fold
181 : decltype(hana::reverse_fold(
182 Sequence{}, hana::type_c<State>, detail::mpl_metafunction<F>
183 ))
184{ };
185
186template <typename Sequence, typename State, typename F>
187using 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//////////////////////////////////////////////////////////////////////////////
204template <typename Sequence, typename Pred>
205struct find_if
206 : decltype(hana::find_if(Sequence{}, detail::mpl_predicate<Pred>))
207{ };
208
209template <typename Sequence, typename T>
210struct find
211 : decltype(hana::find(Sequence{}, hana::type_c<T>))
212{ };
213
214template <typename Sequence, typename T>
215struct contains
216 : decltype(hana::contains(Sequence{}, hana::type_c<T>))
217{ };
218
219template <typename Sequence, typename T>
220struct count
221 : decltype(hana::count(Sequence{}, hana::type_c<T>))
222{ };
223
224template <typename Sequence, typename Pred>
225struct count_if
226 : decltype(hana::count_if(Sequence{}, detail::mpl_predicate<Pred>))
227{ };
228
229template <typename Sequence, typename Pred = mpl::quote2<less>>
230struct min_element
231 : decltype(hana::minimum(Sequence{}, detail::mpl_predicate<Pred>))
232{ };
233
234template <typename Sequence, typename Pred = mpl::quote2<less>>
235struct max_element
236 : decltype(hana::maximum(Sequence{}, detail::mpl_predicate<Pred>))
237{ };
238
239template <typename S1, typename S2, typename Pred = mpl::quote2<std::is_same>>
240struct 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//////////////////////////////////////////////////////////////////////////////
258template <typename Sequence>
259struct copy {
260 using type = decltype(hana::to_tuple(Sequence{}));
261};
262
263template <typename Sequence, typename Pred>
264struct copy_if {
265 using type = decltype(hana::filter(
266 hana::to_tuple(Sequence{}),
267 detail::mpl_predicate<Pred>
268 ));
269};
270
271template <typename Sequence, typename Sequence_or_Op, typename = void>
272struct transform;
273
274template <typename Sequence, typename Op>
275struct transform<Sequence, Op> {
276 using type = decltype(hana::transform(
277 hana::to_tuple(Sequence{}), detail::mpl_metafunction<Op>
278 ));
279};
280
281template <typename S1, typename S2, typename Op>
282struct 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
290template <typename Sequence, typename OldType, typename NewType>
291struct 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
299template <typename Sequence, typename Pred, typename NewType>
300struct 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
308template <typename Sequence, typename T>
309struct remove {
310 using type = decltype(hana::filter(
311 hana::to_tuple(Sequence{}),
312 hana::not_equal.to(hana::type_c<T>)
313 ));
314};
315
316template <typename Sequence, typename Pred>
317struct 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
324template <typename Sequence, typename Pred>
325struct unique {
326 using type = decltype(hana::unique(
327 hana::to_tuple(Sequence{}),
328 detail::mpl_predicate<Pred>
329 ));
330};
331
332template <typename Sequence, typename Pred>
333struct 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
344template <typename Sequence, typename Pred = mpl::quote2<less>>
345struct sort {
346 using type = decltype(hana::sort(
347 hana::to_tuple(Sequence{}), detail::mpl_predicate<Pred>
348 ));
349};
350
351template <typename Sequence>
352struct reverse {
353 using type = decltype(hana::reverse(hana::to_tuple(Sequence{})));
354};
355
356
357//////////////////////////////////////////////////////////////////////////////
358// Runtime algorithms
359//////////////////////////////////////////////////////////////////////////////
360template <typename Sequence, typename F>
361void for_each(F f) {
362 hana::for_each(Sequence{}, [&f](auto t) {
363 f(typename decltype(t)::type{});
364 });
365}
366
367template <typename Sequence, typename TransformOp, typename F>
368void for_each(F f) {
369 for_each<typename transform<Sequence, TransformOp>::type>(f);
370}
371
372} // end namespace hpl
373
374
375template <typename N>
376struct is_odd
377 : hpl::bool_<(N::value % 2)>
378{ };
379
380
381int main() {
382using 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}