1 /*! 2 @file 3 Defines `boost::hana::fold_right`. 4 5 @copyright Louis Dionne 2013-2017 6 Distributed under the Boost Software License, Version 1.0. 7 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) 8 */ 9 10 #ifndef BOOST_HANA_FOLD_RIGHT_HPP 11 #define BOOST_HANA_FOLD_RIGHT_HPP 12 13 #include <boost/hana/fwd/fold_right.hpp> 14 15 #include <boost/hana/concept/foldable.hpp> 16 #include <boost/hana/config.hpp> 17 #include <boost/hana/core/dispatch.hpp> 18 #include <boost/hana/detail/variadic/foldr1.hpp> 19 #include <boost/hana/functional/partial.hpp> 20 #include <boost/hana/fwd/unpack.hpp> 21 22 23 BOOST_HANA_NAMESPACE_BEGIN 24 //! @cond 25 template <typename Xs, typename State, typename F> operator ()(Xs && xs,State && state,F && f) const26 constexpr decltype(auto) fold_right_t::operator()(Xs&& xs, State&& state, F&& f) const { 27 using S = typename hana::tag_of<Xs>::type; 28 using FoldRight = BOOST_HANA_DISPATCH_IF(fold_right_impl<S>, 29 hana::Foldable<S>::value 30 ); 31 32 #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS 33 static_assert(hana::Foldable<S>::value, 34 "hana::fold_right(xs, state, f) requires 'xs' to be Foldable"); 35 #endif 36 37 return FoldRight::apply(static_cast<Xs&&>(xs), 38 static_cast<State&&>(state), 39 static_cast<F&&>(f)); 40 } 41 42 template <typename Xs, typename F> operator ()(Xs && xs,F && f) const43 constexpr decltype(auto) fold_right_t::operator()(Xs&& xs, F&& f) const { 44 using S = typename hana::tag_of<Xs>::type; 45 using FoldRight = BOOST_HANA_DISPATCH_IF(fold_right_impl<S>, 46 hana::Foldable<S>::value 47 ); 48 49 #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS 50 static_assert(hana::Foldable<S>::value, 51 "hana::fold_right(xs, f) requires 'xs' to be Foldable"); 52 #endif 53 54 return FoldRight::apply(static_cast<Xs&&>(xs), static_cast<F&&>(f)); 55 } 56 //! @endcond 57 58 namespace detail { 59 template <typename F, typename State> 60 struct variadic_foldr { 61 F& f; 62 State& state; 63 template <typename ...T> operator ()detail::variadic_foldr64 constexpr decltype(auto) operator()(T&& ...t) const { 65 return detail::variadic::foldr( 66 static_cast<F&&>(f), 67 static_cast<State&&>(state), 68 static_cast<T&&>(t)... 69 ); 70 } 71 }; 72 } 73 74 template <typename T, bool condition> 75 struct fold_right_impl<T, when<condition>> : default_ { 76 // with state 77 template <typename Xs, typename S, typename F> applyfold_right_impl78 static constexpr decltype(auto) apply(Xs&& xs, S&& s, F&& f) { 79 return hana::unpack(static_cast<Xs&&>(xs), 80 detail::variadic_foldr<F, S>{f, s} 81 ); 82 } 83 84 // without state 85 template <typename Xs, typename F> applyfold_right_impl86 static constexpr decltype(auto) apply(Xs&& xs, F&& f) { 87 return hana::unpack(static_cast<Xs&&>(xs), 88 hana::partial( 89 detail::variadic::foldr1, 90 static_cast<F&&>(f) 91 ) 92 ); 93 } 94 }; 95 BOOST_HANA_NAMESPACE_END 96 97 #endif // !BOOST_HANA_FOLD_RIGHT_HPP 98