]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/hana/example/tutorial/appendix_mpl.cpp
162831a6ec1ab5d98aa28e5547aff3273a242395
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)
5 #include <boost/hana.hpp>
6 #include <boost/hana/ext/boost/mpl.hpp>
7 #include <boost/hana/ext/std.hpp>
9 #include <boost/mpl/lambda.hpp>
10 #include <boost/mpl/placeholders.hpp>
11 #include <boost/mpl/quote.hpp>
14 #include <type_traits>
15 namespace hana
= boost::hana
;
16 namespace mpl
= boost::mpl
;
20 //////////////////////////////////////////////////////////////////////////////
22 //////////////////////////////////////////////////////////////////////////////
24 template <typename Pred
>
25 constexpr auto mpl_predicate
= hana::integral(hana::metafunction_class
<
26 typename
mpl::lambda
<Pred
>::type
30 constexpr auto mpl_metafunction
= hana::metafunction_class
<
31 typename
mpl::lambda
<F
>::type
35 //////////////////////////////////////////////////////////////////////////////
37 //////////////////////////////////////////////////////////////////////////////
38 template <typename T
, T v
>
39 using integral_c
= std::integral_constant
<T
, v
>;
42 using int_
= integral_c
<int, i
>;
45 using long_
= integral_c
<long, i
>;
48 using bool_
= integral_c
<bool, b
>;
50 using true_
= bool_
<true>;
51 using false_
= bool_
<false>;
54 //////////////////////////////////////////////////////////////////////////////
55 // Sequences, compile-time integers & al
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
>...>;
64 template <typename T
, T
...v
>
65 using vector_c
= hana::tuple
<hana::integral_constant
<T
, v
>...>;
67 template <typename T
, T from
, T to
>
68 using range_c
= decltype(hana::range_c
<T
, from
, to
>);
71 template <typename T
, typename U
>
72 using pair
= hana::pair
<hana::type
<T
>, hana::type
<U
>>;
75 struct first
: decltype(+hana::first(P
{})) { };
78 struct second
: decltype(+hana::second(P
{})) { };
81 //////////////////////////////////////////////////////////////////////////////
82 // Miscellaneous metafunctions
83 //////////////////////////////////////////////////////////////////////////////
84 template <typename C1
, typename C2
>
86 : bool_
<C1::value
== C2::value
>
89 template <typename C1
, typename C2
>
91 : bool_
<(C1::value
< C2::value
)>
94 template <typename C1
, typename C2
>
96 : bool_
<(C1::value
> C2::value
)>
101 : integral_c
<typename
N::value_type
, N::value
+ 1>
104 //////////////////////////////////////////////////////////////////////////////
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
>
114 : decltype(hana::at(Sequence
{}, N
{}))
117 template <typename Sequence
, long n
>
118 using at_c
= at
<Sequence
, long_
<n
>>;
120 template <typename Sequence
>
122 : decltype(+hana::back(Sequence
{}))
125 template <typename Sequence
>
127 : decltype(hana::is_empty(Sequence
{}))
130 template <typename Sequence
>
132 : decltype(+hana::front(Sequence
{}))
135 template <typename Sequence
>
137 using type
= decltype(hana::drop_back(
138 hana::to_tuple(Sequence
{}), hana::size_c
<1>
142 template <typename Sequence
>
144 using type
= decltype(hana::drop_front(Sequence
{}));
147 template <typename Sequence
, typename T
>
149 using type
= decltype(hana::append(Sequence
{}, hana::type_c
<T
>));
152 template <typename Sequence
, typename T
>
154 using type
= decltype(hana::prepend(Sequence
{}, hana::type_c
<T
>));
157 template <typename Sequence
>
159 : decltype(hana::length(Sequence
{}))
162 //////////////////////////////////////////////////////////////////////////////
163 // Iteration algorithms
165 // Differences with the MPL:
167 // Does not take an optional additional ForwardOp argument.
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
>
174 : decltype(hana::fold(
175 Sequence
{}, hana::type_c
<State
>, detail::mpl_metafunction
<F
>
179 template <typename Sequence
, typename State
, typename F
>
181 : decltype(hana::reverse_fold(
182 Sequence
{}, hana::type_c
<State
>, detail::mpl_metafunction
<F
>
186 template <typename Sequence
, typename State
, typename F
>
187 using accumulate
= fold
<Sequence
, State
, F
>;
189 //////////////////////////////////////////////////////////////////////////////
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.
198 // 2. lower_bound, upper_bound:
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
>
206 : decltype(hana::find_if(Sequence
{}, detail::mpl_predicate
<Pred
>))
209 template <typename Sequence
, typename T
>
211 : decltype(hana::find(Sequence
{}, hana::type_c
<T
>))
214 template <typename Sequence
, typename T
>
216 : decltype(hana::contains(Sequence
{}, hana::type_c
<T
>))
219 template <typename Sequence
, typename T
>
221 : decltype(hana::count(Sequence
{}, hana::type_c
<T
>))
224 template <typename Sequence
, typename Pred
>
226 : decltype(hana::count_if(Sequence
{}, detail::mpl_predicate
<Pred
>))
229 template <typename Sequence
, typename Pred
= mpl::quote2
<less
>>
231 : decltype(hana::minimum(Sequence
{}, detail::mpl_predicate
<Pred
>))
234 template <typename Sequence
, typename Pred
= mpl::quote2
<less
>>
236 : decltype(hana::maximum(Sequence
{}, detail::mpl_predicate
<Pred
>))
239 template <typename S1
, typename S2
, typename Pred
= mpl::quote2
<std::is_same
>>
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
{})))
249 //////////////////////////////////////////////////////////////////////////////
250 // Transformation algorithms
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
>
260 using type
= decltype(hana::to_tuple(Sequence
{}));
263 template <typename Sequence
, typename Pred
>
265 using type
= decltype(hana::filter(
266 hana::to_tuple(Sequence
{}),
267 detail::mpl_predicate
<Pred
>
271 template <typename Sequence
, typename Sequence_or_Op
, typename
= void>
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
>
281 template <typename S1
, typename S2
, typename Op
>
283 using type
= decltype(hana::zip_with(
284 detail::mpl_metafunction
<Op
>,
285 hana::to_tuple(S1
{}),
290 template <typename Sequence
, typename OldType
, typename NewType
>
292 using type
= decltype(hana::replace(
293 hana::to_tuple(Sequence
{}),
294 hana::type_c
<OldType
>,
295 hana::type_c
<NewType
>
299 template <typename Sequence
, typename Pred
, typename NewType
>
301 using type
= decltype(hana::replace_if(
302 hana::to_tuple(Sequence
{}),
303 detail::mpl_predicate
<Pred
>,
304 hana::type_c
<NewType
>
308 template <typename Sequence
, typename T
>
310 using type
= decltype(hana::filter(
311 hana::to_tuple(Sequence
{}),
312 hana::not_equal
.to(hana::type_c
<T
>)
316 template <typename Sequence
, typename Pred
>
318 using type
= decltype(hana::filter(
319 hana::to_tuple(Sequence
{}),
320 hana::compose(hana::not_
, detail::mpl_predicate
<Pred
>)
324 template <typename Sequence
, typename Pred
>
326 using type
= decltype(hana::unique(
327 hana::to_tuple(Sequence
{}),
328 detail::mpl_predicate
<Pred
>
332 template <typename Sequence
, typename Pred
>
334 using hana_pair
= decltype(hana::partition(
335 hana::to_tuple(Sequence
{}),
336 detail::mpl_predicate
<Pred
>
339 decltype(hana::first(hana_pair
{})),
340 decltype(hana::second(hana_pair
{}))
344 template <typename Sequence
, typename Pred
= mpl::quote2
<less
>>
346 using type
= decltype(hana::sort(
347 hana::to_tuple(Sequence
{}), detail::mpl_predicate
<Pred
>
351 template <typename Sequence
>
353 using type
= decltype(hana::reverse(hana::to_tuple(Sequence
{})));
357 //////////////////////////////////////////////////////////////////////////////
358 // Runtime algorithms
359 //////////////////////////////////////////////////////////////////////////////
360 template <typename Sequence
, typename F
>
362 hana::for_each(Sequence
{}, [&f
](auto t
) {
363 f(typename
decltype(t
)::type
{});
367 template <typename Sequence
, typename TransformOp
, typename F
>
369 for_each
<typename transform
<Sequence
, TransformOp
>::type
>(f
);
372 } // end namespace hpl
375 template <typename N
>
377 : hpl::bool_
<(N::value
% 2)>
384 //////////////////////////////////////////////////////////////////////////////
386 //////////////////////////////////////////////////////////////////////////////
390 static_assert(std::is_same
<first
<pair
<int, float>>::type
, int>{}, "");
391 static_assert(std::is_same
<second
<pair
<int, float>>::type
, float>{}, "");
394 //////////////////////////////////////////////////////////////////////////////
396 //////////////////////////////////////////////////////////////////////////////
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, "");
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, "");
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>{}, "");
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
>{}, "");
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>{}, "");
446 using types1
= vector
<long>;
447 using types2
= vector
<long,int>;
448 using types3
= vector
<long,int,char>;
451 using result1
= pop_back
<types1
>::type
;
452 using result2
= pop_back
<types2
>::type
;
453 using result3
= pop_back
<types3
>::type
;
455 static_assert(size
<result1
>::value
== 0, "");
456 static_assert(size
<result2
>::value
== 1, "");
457 static_assert(size
<result3
>::value
== 2, "");
459 static_assert(std::is_same
< back
<result2
>::type
, long>{}, "");
460 static_assert(std::is_same
< back
<result3
>::type
, int>{}, "");
465 using types1
= vector
<long>;
466 using types2
= vector
<int,long>;
467 using types3
= vector
<char,int,long>;
469 using result1
= pop_front
<types1
>::type
;
470 using result2
= pop_front
<types2
>::type
;
471 using result3
= pop_front
<types3
>::type
;
473 static_assert(size
<result1
>::value
== 0, "");
474 static_assert(size
<result2
>::value
== 1, "");
475 static_assert(size
<result3
>::value
== 2, "");
477 static_assert(std::is_same
<front
<result2
>::type
, long>{}, "");
478 static_assert(std::is_same
<front
<result3
>::type
, int>{}, "");
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, "");
491 using v
= vector_c
<int,1,2,3,5,8,13,21>;
492 static_assert(size
<v
>{} == 7u, "");
494 using fibonacci
= push_front
<v
, int_
<1>>::type
;
495 static_assert(size
<fibonacci
>{} == 8u, "");
499 vector_c
<int,1,1,2,3,5,8,13,21>,
500 equal_to
<mpl::_
, mpl::_
>
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>;
510 static_assert(size
<empty_list
>{} == 0u, "");
511 static_assert(size
<numbers
>{} == 6u, "");
512 static_assert(size
<more_numbers
>{} == 100u, "");
516 //////////////////////////////////////////////////////////////////////////////
517 // Iteration algorithms
518 //////////////////////////////////////////////////////////////////////////////
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
>,
529 static_assert(number_of_floats
{} == 4, "");
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
>,
542 static_assert(equal
<negatives
, result
>{}, "");
545 //////////////////////////////////////////////////////////////////////////////
547 //////////////////////////////////////////////////////////////////////////////
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>{}, "");
558 using types
= vector
<char,int,unsigned,long,unsigned long>;
559 static_assert(std::is_same
<find
<types
, unsigned>::type
, unsigned>{}, "");
564 using types
= vector
<char,int,unsigned,long,unsigned long>;
565 static_assert(!contains
<types
, bool>{}, "");
570 using types
= vector
<int,char,long,short,char,short,double,long>;
571 static_assert(count
<types
, short>{} == 2u, "");
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, "");
582 // min_element (MPL's example is completely broken)
586 // max_element (MPL's example is completely broken)
592 using s1
= vector
<char,int,unsigned,long,unsigned long>;
593 using s2
= vector
<char,int,unsigned,long>;
594 static_assert(!equal
<s1
,s2
>{}, "");
598 //////////////////////////////////////////////////////////////////////////////
599 // Transformaton algorithms
600 //////////////////////////////////////////////////////////////////////////////
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
>>{}, "");
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>>{}, "");
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
>{}, "");
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
>{}, "");
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
>>{}, "");
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>>{}, "");
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
>>{}, "");
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
>{}, "");
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>>{}, "");
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::_
>>{}, "");
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>>{}, "");
684 //////////////////////////////////////////////////////////////////////////////
685 // Runtime algorithms
686 //////////////////////////////////////////////////////////////////////////////
690 auto value_printer
= [](auto x
) {
691 std::cout
<< x
<< '\n';
694 for_each
<range_c
<int, 0, 10> >(value_printer
);