infinite_list.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  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. #include <boost/hana/assert.hpp>
  5. #include <boost/hana/at.hpp>
  6. #include <boost/hana/bool.hpp>
  7. #include <boost/hana/drop_front.hpp>
  8. #include <boost/hana/eval.hpp>
  9. #include <boost/hana/front.hpp>
  10. #include <boost/hana/functional/fix.hpp>
  11. #include <boost/hana/functional/iterate.hpp>
  12. #include <boost/hana/fwd/at.hpp>
  13. #include <boost/hana/fwd/empty.hpp>
  14. #include <boost/hana/fwd/prepend.hpp>
  15. #include <boost/hana/integral_constant.hpp>
  16. #include <boost/hana/is_empty.hpp>
  17. #include <boost/hana/lazy.hpp>
  18. #include <boost/hana/not.hpp>
  19. #include <boost/hana/value.hpp>
  20. #include <cstddef>
  21. namespace hana = boost::hana;
  22. // A naive implementation of a lazy compile-time list, i.e. a tuple that can
  23. // potentially have an infinite number of elements (but that infinity must be
  24. // determinable at compile-time).
  25. struct LazyList;
  26. template <typename X, typename Xs>
  27. struct lazy_cons_type {
  28. X x;
  29. Xs xs;
  30. using hana_tag = LazyList;
  31. };
  32. auto lazy_cons = [](auto x, auto xs) {
  33. return lazy_cons_type<decltype(x), decltype(xs)>{x, xs};
  34. };
  35. struct lazy_nil_type { using hana_tag = LazyList; };
  36. constexpr lazy_nil_type lazy_nil{};
  37. auto repeat = hana::fix([](auto repeat, auto x) {
  38. return lazy_cons(x, hana::make_lazy(repeat)(x));
  39. });
  40. namespace boost { namespace hana {
  41. //////////////////////////////////////////////////////////////////////////
  42. // Iterable
  43. //////////////////////////////////////////////////////////////////////////
  44. template <>
  45. struct at_impl<LazyList> {
  46. template <typename Xs, typename N>
  47. static constexpr auto apply(Xs&& lcons, N const& n) {
  48. return hana::drop_front(lcons, n).x;
  49. }
  50. };
  51. namespace detail {
  52. struct eval_tail {
  53. template <typename Xs>
  54. constexpr auto operator()(Xs const& lcons) const {
  55. return hana::eval(lcons.xs);
  56. }
  57. constexpr auto operator()(lazy_nil_type const&) const {
  58. return lazy_nil;
  59. }
  60. };
  61. }
  62. template <>
  63. struct drop_front_impl<LazyList> {
  64. template <typename Xs, typename N>
  65. static constexpr auto apply(Xs&& lcons, N const&) {
  66. return hana::iterate<N::value>(detail::eval_tail{}, lcons);
  67. }
  68. };
  69. template <>
  70. struct is_empty_impl<LazyList> {
  71. template <typename Xs>
  72. static constexpr auto apply(Xs const&)
  73. { return hana::false_c; }
  74. static constexpr auto apply(lazy_nil_type const&)
  75. { return hana::true_c; }
  76. };
  77. //////////////////////////////////////////////////////////////////////////
  78. // MonadPlus
  79. //////////////////////////////////////////////////////////////////////////
  80. template <>
  81. struct prepend_impl<LazyList> {
  82. template <typename Xs, typename X>
  83. static constexpr auto apply(Xs xs, X x)
  84. { return lazy_cons(x, hana::make_lazy(xs)); }
  85. };
  86. template <>
  87. struct empty_impl<LazyList> {
  88. static constexpr auto apply()
  89. { return lazy_nil; }
  90. };
  91. }}
  92. int main() {
  93. BOOST_HANA_CONSTANT_CHECK(!hana::is_empty(repeat(1)));
  94. BOOST_HANA_CONSTEXPR_CHECK(hana::front(repeat(1)) == 1);
  95. BOOST_HANA_CONSTEXPR_CHECK(hana::at(repeat(1), hana::size_c<10>) == 1);
  96. }