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/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 // A naive implementation of a lazy compile-time list, i.e. a tuple that can
27 // potentially have an infinite number of elements (but that infinity must be
28 // determinable at compile-time).
29
30 struct LazyList;
31
32 template <typename X, typename Xs>
33 struct lazy_cons_type {
34 X x;
35 Xs xs;
36 using hana_tag = LazyList;
37 };
38
__anon031d66920102(auto x, auto xs) 39 auto lazy_cons = [](auto x, auto xs) {
40 return lazy_cons_type<decltype(x), decltype(xs)>{x, xs};
41 };
42
43 struct lazy_nil_type { using hana_tag = LazyList; };
44
45 constexpr lazy_nil_type lazy_nil{};
46
__anon031d66920202(auto repeat, auto x) 47 auto repeat = hana::fix([](auto repeat, auto x) {
48 return lazy_cons(x, hana::make_lazy(repeat)(x));
49 });
50
51 namespace boost { namespace hana {
52 //////////////////////////////////////////////////////////////////////////
53 // Iterable
54 //////////////////////////////////////////////////////////////////////////
55 template <>
56 struct at_impl<LazyList> {
57 template <typename Xs, typename N>
applyboost::hana::at_impl58 static constexpr auto apply(Xs&& lcons, N const& n) {
59 return hana::drop_front(lcons, n).x;
60 }
61 };
62
63 namespace detail {
64 struct eval_tail {
65 template <typename Xs>
operator ()boost::hana::detail::eval_tail66 constexpr auto operator()(Xs const& lcons) const {
67 return hana::eval(lcons.xs);
68 }
69
operator ()boost::hana::detail::eval_tail70 constexpr auto operator()(lazy_nil_type const&) const {
71 return lazy_nil;
72 }
73 };
74 }
75
76 template <>
77 struct drop_front_impl<LazyList> {
78 template <typename Xs, typename N>
applyboost::hana::drop_front_impl79 static constexpr auto apply(Xs&& lcons, N const&) {
80 return hana::iterate<N::value>(detail::eval_tail{}, lcons);
81 }
82 };
83
84 template <>
85 struct is_empty_impl<LazyList> {
86 template <typename Xs>
applyboost::hana::is_empty_impl87 static constexpr auto apply(Xs const&)
88 { return hana::false_c; }
89
applyboost::hana::is_empty_impl90 static constexpr auto apply(lazy_nil_type const&)
91 { return hana::true_c; }
92 };
93
94 //////////////////////////////////////////////////////////////////////////
95 // MonadPlus
96 //////////////////////////////////////////////////////////////////////////
97 template <>
98 struct prepend_impl<LazyList> {
99 template <typename Xs, typename X>
applyboost::hana::prepend_impl100 static constexpr auto apply(Xs xs, X x)
101 { return lazy_cons(x, hana::make_lazy(xs)); }
102 };
103
104 template <>
105 struct empty_impl<LazyList> {
applyboost::hana::empty_impl106 static constexpr auto apply()
107 { return lazy_nil; }
108 };
109 }}
110
111
main()112 int main() {
113 BOOST_HANA_CONSTANT_CHECK(!hana::is_empty(repeat(1)));
114 BOOST_HANA_CONSTEXPR_CHECK(hana::front(repeat(1)) == 1);
115 BOOST_HANA_CONSTEXPR_CHECK(hana::at(repeat(1), hana::size_c<10>) == 1);
116 }
117