• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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