reverse_partial.hpp 3.2 KB

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