1 /*! 2 @file 3 Defines `boost::hana::reverse_partial`. 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_FUNCTIONAL_REVERSE_PARTIAL_HPP 11 #define BOOST_HANA_FUNCTIONAL_REVERSE_PARTIAL_HPP 12 13 #include <boost/hana/basic_tuple.hpp> 14 #include <boost/hana/config.hpp> 15 #include <boost/hana/detail/decay.hpp> 16 17 #include <cstddef> 18 #include <utility> 19 20 21 BOOST_HANA_NAMESPACE_BEGIN 22 //! @ingroup group-functional 23 //! Partially apply a function to some arguments. 24 //! 25 //! Given a function `f` and some arguments, `reverse_partial` returns a 26 //! new function corresponding to `f` whose last arguments are partially 27 //! applied. Specifically, `reverse_partial(f, x...)` is a function such 28 //! that 29 //! @code 30 //! reverse_partial(f, x...)(y...) == f(y..., x...) 31 //! @endcode 32 //! 33 //! @note 34 //! The arity of `f` must match the total number of arguments passed to 35 //! it, i.e. `sizeof...(x) + sizeof...(y)`. 36 //! 37 //! 38 //! Example 39 //! ------- 40 //! @include example/functional/reverse_partial.cpp 41 #ifdef BOOST_HANA_DOXYGEN_INVOKED __anonfdaaa70c0102(auto&& f, auto&& ...x) 42 constexpr auto reverse_partial = [](auto&& f, auto&& ...x) { 43 return [perfect-capture](auto&& ...y) -> decltype(auto) { 44 return forwarded(f)(forwarded(y)..., forwarded(x)...); 45 }; 46 }; 47 #else 48 template <typename Indices, typename F, typename ...X> 49 struct reverse_partial_t; 50 51 struct make_reverse_partial_t { 52 struct secret { }; 53 template <typename F, typename ...X> 54 constexpr reverse_partial_t< 55 std::make_index_sequence<sizeof...(X)>, 56 typename detail::decay<F>::type, 57 typename detail::decay<X>::type... 58 > operator()(F&& f, X&& ...x) const { 59 return {secret{}, static_cast<F&&>(f), static_cast<X&&>(x)...}; 60 } 61 }; 62 63 template <std::size_t ...n, typename F, typename ...X> 64 struct reverse_partial_t<std::index_sequence<n...>, F, X...> { 65 reverse_partial_t() = default; 66 67 template <typename ...T> 68 constexpr reverse_partial_t(make_reverse_partial_t::secret, T&& ...t) 69 : storage_{static_cast<T&&>(t)...} 70 { } 71 72 basic_tuple<F, X...> storage_; 73 74 template <typename ...Y> 75 constexpr decltype(auto) operator()(Y&& ...y) const& { 76 return hana::at_c<0>(storage_)( 77 static_cast<Y&&>(y)..., 78 hana::at_c<n+1>(storage_)... 79 ); 80 } 81 82 template <typename ...Y> 83 constexpr decltype(auto) operator()(Y&& ...y) & { 84 return hana::at_c<0>(storage_)( 85 static_cast<Y&&>(y)..., 86 hana::at_c<n+1>(storage_)... 87 ); 88 } 89 90 template <typename ...Y> 91 constexpr decltype(auto) operator()(Y&& ...y) && { 92 return static_cast<F&&>(hana::at_c<0>(storage_))( 93 static_cast<Y&&>(y)..., 94 static_cast<X&&>(hana::at_c<n+1>(storage_))... 95 ); 96 } 97 }; 98 99 constexpr make_reverse_partial_t reverse_partial{}; 100 #endif 101 BOOST_HANA_NAMESPACE_END 102 103 #endif // !BOOST_HANA_FUNCTIONAL_REVERSE_PARTIAL_HPP 104