scan_left.hpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. /*!
  2. @file
  3. Defines `boost::hana::scan_left`.
  4. @copyright Louis Dionne 2013-2017
  5. Distributed under the Boost Software License, Version 1.0.
  6. (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
  7. */
  8. #ifndef BOOST_HANA_SCAN_LEFT_HPP
  9. #define BOOST_HANA_SCAN_LEFT_HPP
  10. #include <boost/hana/fwd/scan_left.hpp>
  11. #include <boost/hana/at.hpp>
  12. #include <boost/hana/concept/sequence.hpp>
  13. #include <boost/hana/config.hpp>
  14. #include <boost/hana/core/dispatch.hpp>
  15. #include <boost/hana/core/make.hpp>
  16. #include <boost/hana/empty.hpp>
  17. #include <boost/hana/length.hpp>
  18. #include <boost/hana/prepend.hpp>
  19. #include <cstddef>
  20. #include <utility>
  21. BOOST_HANA_NAMESPACE_BEGIN
  22. //! @cond
  23. template <typename Xs, typename F>
  24. constexpr auto scan_left_t::operator()(Xs&& xs, F const& f) const {
  25. using S = typename hana::tag_of<Xs>::type;
  26. using ScanLeft = BOOST_HANA_DISPATCH_IF(scan_left_impl<S>,
  27. hana::Sequence<S>::value
  28. );
  29. #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
  30. static_assert(hana::Sequence<S>::value,
  31. "hana::scan_left(xs, f) requires 'xs' to be a Sequence");
  32. #endif
  33. return ScanLeft::apply(static_cast<Xs&&>(xs), f);
  34. }
  35. template <typename Xs, typename State, typename F>
  36. constexpr auto scan_left_t::operator()(Xs&& xs, State&& state, F const& f) const {
  37. using S = typename hana::tag_of<Xs>::type;
  38. using ScanLeft = BOOST_HANA_DISPATCH_IF(scan_left_impl<S>,
  39. hana::Sequence<S>::value
  40. );
  41. #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
  42. static_assert(hana::Sequence<S>::value,
  43. "hana::scan_left(xs, state, f) requires 'xs' to be a Sequence");
  44. #endif
  45. return ScanLeft::apply(static_cast<Xs&&>(xs),
  46. static_cast<State&&>(state), f);
  47. }
  48. //! @endcond
  49. template <typename S, bool condition>
  50. struct scan_left_impl<S, when<condition>> : default_ {
  51. // Without initial state
  52. template <typename Xs, typename F, std::size_t n1, std::size_t n2, std::size_t ...ns>
  53. static constexpr auto
  54. apply1_impl(Xs&& xs, F const& f, std::index_sequence<n1, n2, ns...>) {
  55. static_assert(n1 == 0, "logic error in Boost.Hana: file a bug report");
  56. // Use scan_left with the first element as an initial state.
  57. return scan_left_impl::apply_impl(
  58. static_cast<Xs&&>(xs),
  59. hana::at_c<0>(static_cast<Xs&&>(xs)),
  60. f, std::index_sequence<n2, ns...>{}
  61. );
  62. }
  63. template <typename Xs, typename F, std::size_t n>
  64. static constexpr auto apply1_impl(Xs&& xs, F const&, std::index_sequence<n>) {
  65. return hana::make<S>(hana::at_c<n>(static_cast<Xs&&>(xs)));
  66. }
  67. template <typename Xs, typename F>
  68. static constexpr auto apply1_impl(Xs&&, F const&, std::index_sequence<>) {
  69. return hana::empty<S>();
  70. }
  71. template <typename Xs, typename F>
  72. static constexpr auto apply(Xs&& xs, F const& f) {
  73. constexpr std::size_t Len = decltype(hana::length(xs))::value;
  74. return scan_left_impl::apply1_impl(static_cast<Xs&&>(xs),
  75. f, std::make_index_sequence<Len>{});
  76. }
  77. // With initial state
  78. template <typename Xs, typename State, typename F,
  79. std::size_t n1, std::size_t n2, std::size_t ...ns>
  80. static constexpr auto
  81. apply_impl(Xs&& xs, State&& state, F const& f,
  82. std::index_sequence<n1, n2, ns...>)
  83. {
  84. auto rest = scan_left_impl::apply_impl(
  85. static_cast<Xs&&>(xs),
  86. f(state, hana::at_c<n1>(static_cast<Xs&&>(xs))),
  87. f, std::index_sequence<n2, ns...>{});
  88. return hana::prepend(std::move(rest), static_cast<State&&>(state));
  89. }
  90. template <typename Xs, typename State, typename F, std::size_t n>
  91. static constexpr auto
  92. apply_impl(Xs&& xs, State&& state, F const& f, std::index_sequence<n>) {
  93. auto new_state = f(state, hana::at_c<n>(static_cast<Xs&&>(xs)));
  94. return hana::make<S>(static_cast<State&&>(state), std::move(new_state));
  95. }
  96. template <typename Xs, typename State, typename F>
  97. static constexpr auto
  98. apply_impl(Xs&&, State&& state, F const&, std::index_sequence<>) {
  99. return hana::make<S>(static_cast<State&&>(state));
  100. }
  101. template <typename Xs, typename State, typename F>
  102. static constexpr auto apply(Xs&& xs, State&& state, F const& f) {
  103. constexpr std::size_t Len = decltype(hana::length(xs))::value;
  104. return scan_left_impl::apply_impl(static_cast<Xs&&>(xs),
  105. static_cast<State&&>(state),
  106. f, std::make_index_sequence<Len>{});
  107. }
  108. };
  109. BOOST_HANA_NAMESPACE_END
  110. #endif // !BOOST_HANA_SCAN_LEFT_HPP