]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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/assert.hpp> | |
6 | #include <boost/hana/at.hpp> | |
7 | #include <boost/hana/bool.hpp> | |
8 | #include <boost/hana/drop_front.hpp> | |
9 | #include <boost/hana/eval.hpp> | |
10 | #include <boost/hana/front.hpp> | |
11 | #include <boost/hana/functional/fix.hpp> | |
12 | #include <boost/hana/functional/iterate.hpp> | |
13 | #include <boost/hana/fwd/at.hpp> | |
14 | #include <boost/hana/fwd/empty.hpp> | |
15 | #include <boost/hana/fwd/prepend.hpp> | |
16 | #include <boost/hana/integral_constant.hpp> | |
17 | #include <boost/hana/is_empty.hpp> | |
18 | #include <boost/hana/lazy.hpp> | |
19 | #include <boost/hana/not.hpp> | |
20 | #include <boost/hana/value.hpp> | |
21 | ||
22 | #include <cstddef> | |
23 | namespace hana = boost::hana; | |
24 | ||
25 | ||
26 | struct LazyList; | |
27 | ||
28 | template <typename X, typename Xs> | |
29 | struct lazy_cons_type { | |
30 | X x; | |
31 | Xs xs; | |
32 | using hana_tag = LazyList; | |
33 | }; | |
34 | ||
35 | auto lazy_cons = [](auto x, auto xs) { | |
36 | return lazy_cons_type<decltype(x), decltype(xs)>{x, xs}; | |
37 | }; | |
38 | ||
39 | struct lazy_nil_type { using hana_tag = LazyList; }; | |
40 | ||
41 | constexpr lazy_nil_type lazy_nil{}; | |
42 | ||
43 | auto repeat = hana::fix([](auto repeat, auto x) { | |
44 | return lazy_cons(x, hana::make_lazy(repeat)(x)); | |
45 | }); | |
46 | ||
47 | namespace boost { namespace hana { | |
48 | ////////////////////////////////////////////////////////////////////////// | |
49 | // Iterable | |
50 | ////////////////////////////////////////////////////////////////////////// | |
51 | template <> | |
52 | struct at_impl<LazyList> { | |
53 | template <typename Xs, typename N> | |
54 | static constexpr auto apply(Xs&& lcons, N const& n) { | |
55 | return hana::drop_front(lcons, n).x; | |
56 | } | |
57 | }; | |
58 | ||
59 | namespace detail { | |
60 | struct eval_tail { | |
61 | template <typename Xs> | |
62 | constexpr auto operator()(Xs const& lcons) const { | |
63 | return hana::eval(lcons.xs); | |
64 | } | |
65 | ||
66 | constexpr auto operator()(lazy_nil_type const&) const { | |
67 | return lazy_nil; | |
68 | } | |
69 | }; | |
70 | } | |
71 | ||
72 | template <> | |
73 | struct drop_front_impl<LazyList> { | |
74 | template <typename Xs, typename N> | |
75 | static constexpr auto apply(Xs&& lcons, N const&) { | |
76 | return hana::iterate<N::value>(detail::eval_tail{}, lcons); | |
77 | } | |
78 | }; | |
79 | ||
80 | template <> | |
81 | struct is_empty_impl<LazyList> { | |
82 | template <typename Xs> | |
83 | static constexpr auto apply(Xs const&) | |
84 | { return hana::false_c; } | |
85 | ||
86 | static constexpr auto apply(lazy_nil_type const&) | |
87 | { return hana::true_c; } | |
88 | }; | |
89 | ||
90 | ////////////////////////////////////////////////////////////////////////// | |
91 | // MonadPlus | |
92 | ////////////////////////////////////////////////////////////////////////// | |
93 | template <> | |
94 | struct prepend_impl<LazyList> { | |
95 | template <typename Xs, typename X> | |
96 | static constexpr auto apply(Xs xs, X x) | |
97 | { return lazy_cons(x, hana::make_lazy(xs)); } | |
98 | }; | |
99 | ||
100 | template <> | |
101 | struct empty_impl<LazyList> { | |
102 | static constexpr auto apply() | |
103 | { return lazy_nil; } | |
104 | }; | |
105 | }} | |
106 | ||
107 | ||
108 | int main() { | |
109 | BOOST_HANA_CONSTANT_CHECK(!hana::is_empty(repeat(1))); | |
110 | BOOST_HANA_CONSTEXPR_CHECK(hana::front(repeat(1)) == 1); | |
111 | BOOST_HANA_CONSTEXPR_CHECK(hana::at(repeat(1), hana::size_c<10>) == 1); | |
112 | } |