capture.hpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. /*!
  2. @file
  3. Defines `boost::hana::capture`.
  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_CAPTURE_HPP
  9. #define BOOST_HANA_FUNCTIONAL_CAPTURE_HPP
  10. #include <boost/hana/basic_tuple.hpp>
  11. #include <boost/hana/config.hpp>
  12. #include <boost/hana/detail/decay.hpp>
  13. #include <boost/hana/functional/partial.hpp>
  14. #include <cstddef>
  15. #include <utility>
  16. BOOST_HANA_NAMESPACE_BEGIN
  17. //! @ingroup group-functional
  18. //! Create a function capturing the given variables.
  19. //!
  20. //! Given 0 or more variables, `capture` creates a closure that can be
  21. //! used to partially apply a function. This is very similar to `partial`,
  22. //! except that `capture` allows the partially applied function to be
  23. //! specified later. Specifically, `capture(vars...)` is a function object
  24. //! taking a function `f` and returning `f` partially applied to `vars...`.
  25. //! In other words,
  26. //! @code
  27. //! capture(vars...)(f)(args...) == f(vars..., args...)
  28. //! @endcode
  29. //!
  30. //! @note
  31. //! The arity of `f` must match the total number of arguments passed to
  32. //! it, i.e. `sizeof...(vars) + sizeof...(args)`.
  33. //!
  34. //!
  35. //! Example
  36. //! -------
  37. //! @include example/functional/capture.cpp
  38. #ifdef BOOST_HANA_DOXYGEN_INVOKED
  39. constexpr auto capture = [](auto&& ...variables) {
  40. return [perfect-capture](auto&& f) {
  41. return [perfect-capture](auto&& ...args) -> decltype(auto) {
  42. return forwarded(f)(forwarded(variables)..., forwarded(args)...);
  43. };
  44. };
  45. };
  46. #else
  47. namespace detail {
  48. template <typename F, typename Closure, std::size_t ...i>
  49. constexpr auto apply_capture(F&& f, Closure&& closure, std::index_sequence<i...>) {
  50. return hana::partial(static_cast<F&&>(f),
  51. hana::at_c<i>(static_cast<Closure&&>(closure).storage_)...
  52. );
  53. }
  54. }
  55. template <typename ...X>
  56. struct capture_t;
  57. struct make_capture_t {
  58. struct secret { };
  59. template <typename ...X>
  60. constexpr capture_t<typename detail::decay<X>::type...>
  61. operator()(X&& ...x) const {
  62. return {secret{}, static_cast<X&&>(x)...};
  63. }
  64. };
  65. template <typename ...X>
  66. struct capture_t {
  67. template <typename ...Y>
  68. constexpr capture_t(make_capture_t::secret, Y&& ...y)
  69. : storage_{static_cast<Y&&>(y)...}
  70. { }
  71. basic_tuple<X...> storage_;
  72. template <typename F>
  73. constexpr auto operator()(F&& f) const& {
  74. return detail::apply_capture(
  75. static_cast<F&&>(f), *this,
  76. std::make_index_sequence<sizeof...(X)>{}
  77. );
  78. }
  79. template <typename F>
  80. constexpr auto operator()(F&& f) & {
  81. return detail::apply_capture(
  82. static_cast<F&&>(f), *this,
  83. std::make_index_sequence<sizeof...(X)>{}
  84. );
  85. }
  86. template <typename F>
  87. constexpr auto operator()(F&& f) && {
  88. return detail::apply_capture(
  89. static_cast<F&&>(f), static_cast<capture_t&&>(*this),
  90. std::make_index_sequence<sizeof...(X)>{}
  91. );
  92. }
  93. };
  94. constexpr make_capture_t capture{};
  95. #endif
  96. BOOST_HANA_NAMESPACE_END
  97. #endif // !BOOST_HANA_FUNCTIONAL_CAPTURE_HPP