scan_right.hpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. /*!
  2. @file
  3. Defines `boost::hana::scan_right`.
  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_RIGHT_HPP
  9. #define BOOST_HANA_SCAN_RIGHT_HPP
  10. #include <boost/hana/fwd/scan_right.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/front.hpp>
  18. #include <boost/hana/length.hpp>
  19. #include <boost/hana/prepend.hpp>
  20. #include <cstddef>
  21. #include <utility>
  22. BOOST_HANA_NAMESPACE_BEGIN
  23. //! @cond
  24. template <typename Xs, typename F>
  25. constexpr auto scan_right_t::operator()(Xs&& xs, F const& f) const {
  26. using S = typename hana::tag_of<Xs>::type;
  27. using ScanRight = BOOST_HANA_DISPATCH_IF(scan_right_impl<S>,
  28. hana::Sequence<S>::value
  29. );
  30. #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
  31. static_assert(hana::Sequence<S>::value,
  32. "hana::scan_right(xs, f) requires 'xs' to be a Sequence");
  33. #endif
  34. return ScanRight::apply(static_cast<Xs&&>(xs), f);
  35. }
  36. template <typename Xs, typename State, typename F>
  37. constexpr auto scan_right_t::operator()(Xs&& xs, State&& state, F const& f) const {
  38. using S = typename hana::tag_of<Xs>::type;
  39. using ScanRight = BOOST_HANA_DISPATCH_IF(scan_right_impl<S>,
  40. hana::Sequence<S>::value
  41. );
  42. #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
  43. static_assert(hana::Sequence<S>::value,
  44. "hana::scan_right(xs, state, f) requires 'xs' to be a Sequence");
  45. #endif
  46. return ScanRight::apply(static_cast<Xs&&>(xs),
  47. static_cast<State&&>(state), f);
  48. }
  49. //! @endcond
  50. template <typename S, bool condition>
  51. struct scan_right_impl<S, when<condition>> : default_ {
  52. // Without initial state
  53. template <typename Xs, typename F, std::size_t n1, std::size_t n2, std::size_t ...ns>
  54. static constexpr auto
  55. apply1_impl(Xs&& xs, F const& f, std::index_sequence<n1, n2, ns...>) {
  56. auto rest = scan_right_impl::apply1_impl(static_cast<Xs&&>(xs),
  57. f, std::index_sequence<n2, ns...>{});
  58. auto element = f(hana::at_c<n1>(static_cast<Xs&&>(xs)), hana::front(rest));
  59. return hana::prepend(std::move(rest), std::move(element));
  60. }
  61. template <typename Xs, typename F, std::size_t n>
  62. static constexpr auto apply1_impl(Xs&& xs, F const&, std::index_sequence<n>) {
  63. return hana::make<S>(hana::at_c<n>(static_cast<Xs&&>(xs)));
  64. }
  65. template <typename Xs, typename F>
  66. static constexpr auto apply1_impl(Xs&&, F const&, std::index_sequence<>) {
  67. return hana::empty<S>();
  68. }
  69. template <typename Xs, typename F>
  70. static constexpr auto apply(Xs&& xs, F const& f) {
  71. constexpr std::size_t Len = decltype(hana::length(xs))::value;
  72. return scan_right_impl::apply1_impl(static_cast<Xs&&>(xs),
  73. f, std::make_index_sequence<Len>{});
  74. }
  75. // With initial state
  76. template <typename Xs, typename State, typename F,
  77. std::size_t n1, std::size_t n2, std::size_t ...ns>
  78. static constexpr auto
  79. apply_impl(Xs&& xs, State&& state, F const& f,
  80. std::index_sequence<n1, n2, ns...>)
  81. {
  82. auto rest = scan_right_impl::apply_impl(static_cast<Xs&&>(xs),
  83. static_cast<State&&>(state),
  84. f, std::index_sequence<n2, ns...>{});
  85. auto element = f(hana::at_c<n1>(static_cast<Xs&&>(xs)), hana::front(rest));
  86. return hana::prepend(std::move(rest), std::move(element));
  87. }
  88. template <typename Xs, typename State, typename F, std::size_t n>
  89. static constexpr auto
  90. apply_impl(Xs&& xs, State&& state, F const& f, std::index_sequence<n>) {
  91. auto element = f(hana::at_c<n>(static_cast<Xs&&>(xs)), state);
  92. return hana::make<S>(std::move(element), static_cast<State&&>(state));
  93. }
  94. template <typename Xs, typename State, typename F>
  95. static constexpr auto
  96. apply_impl(Xs&&, State&& state, F const&, std::index_sequence<>) {
  97. return hana::make<S>(static_cast<State&&>(state));
  98. }
  99. template <typename Xs, typename State, typename F>
  100. static constexpr auto apply(Xs&& xs, State&& state, F const& f) {
  101. constexpr std::size_t Len = decltype(hana::length(xs))::value;
  102. return scan_right_impl::apply_impl(static_cast<Xs&&>(xs),
  103. static_cast<State&&>(state),
  104. f, std::make_index_sequence<Len>{});
  105. }
  106. };
  107. BOOST_HANA_NAMESPACE_END
  108. #endif // !BOOST_HANA_SCAN_RIGHT_HPP