partial.hpp 3.2 KB

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