]>
Commit | Line | Data |
---|---|---|
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> | |
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 | } |