• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.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>
for_each(F 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>
for_each(F 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 
main()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 }
698