1 /*! 2 @file 3 Defines `boost::hana::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_PARTIAL_HPP 11 #define BOOST_HANA_FUNCTIONAL_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, `partial` returns a new 26 //! function corresponding to the partially applied function `f`. This 27 //! allows providing some arguments to a function and letting the rest 28 //! of the arguments be provided later. Specifically, `partial(f, x...)` 29 //! is a function such that 30 //! @code 31 //! partial(f, x...)(y...) == f(x..., y...) 32 //! @endcode 33 //! 34 //! @note 35 //! The arity of `f` must match the total number of arguments passed to 36 //! it, i.e. `sizeof...(x) + sizeof...(y)`. 37 //! 38 //! 39 //! Example 40 //! ------- 41 //! @include example/functional/partial.cpp 42 #ifdef BOOST_HANA_DOXYGEN_INVOKED __anonb7cf425f0102(auto&& f, auto&& ...x) 43 constexpr auto partial = [](auto&& f, auto&& ...x) { 44 return [perfect-capture](auto&& ...y) -> decltype(auto) { 45 return forwarded(f)(forwarded(x)..., forwarded(y)...); 46 }; 47 }; 48 #else 49 template <typename Indices, typename F, typename ...X> 50 struct partial_t; 51 52 struct make_partial_t { 53 struct secret { }; 54 template <typename F, typename ...X> 55 constexpr partial_t< 56 std::make_index_sequence<sizeof...(X)>, 57 typename detail::decay<F>::type, 58 typename detail::decay<X>::type... 59 > 60 operator()(F&& f, X&& ...x) const { 61 return {secret{}, static_cast<F&&>(f), static_cast<X&&>(x)...}; 62 } 63 }; 64 65 template <std::size_t ...n, typename F, typename ...X> 66 struct partial_t<std::index_sequence<n...>, F, X...> { 67 partial_t() = default; 68 69 template <typename ...T> 70 constexpr partial_t(make_partial_t::secret, T&& ...t) 71 : storage_{static_cast<T&&>(t)...} 72 { } 73 74 basic_tuple<F, X...> storage_; 75 76 template <typename ...Y> 77 constexpr decltype(auto) operator()(Y&& ...y) const& { 78 return hana::at_c<0>(storage_)( 79 hana::at_c<n+1>(storage_)..., 80 static_cast<Y&&>(y)... 81 ); 82 } 83 84 template <typename ...Y> 85 constexpr decltype(auto) operator()(Y&& ...y) & { 86 return hana::at_c<0>(storage_)( 87 hana::at_c<n+1>(storage_)..., 88 static_cast<Y&&>(y)... 89 ); 90 } 91 92 template <typename ...Y> 93 constexpr decltype(auto) operator()(Y&& ...y) && { 94 return static_cast<F&&>(hana::at_c<0>(storage_))( 95 static_cast<X&&>(hana::at_c<n+1>(storage_))..., 96 static_cast<Y&&>(y)... 97 ); 98 } 99 }; 100 101 constexpr make_partial_t partial{}; 102 #endif 103 BOOST_HANA_NAMESPACE_END 104 105 #endif // !BOOST_HANA_FUNCTIONAL_PARTIAL_HPP 106