capture.hpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /*=============================================================================
  2. Copyright (c) 2015 Paul Fultz II
  3. capture.h
  4. Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. ==============================================================================*/
  7. #ifndef BOOST_HOF_GUARD_CAPTURE_H
  8. #define BOOST_HOF_GUARD_CAPTURE_H
  9. #include <boost/hof/detail/callable_base.hpp>
  10. #include <boost/hof/detail/compressed_pair.hpp>
  11. #include <boost/hof/reveal.hpp>
  12. #include <boost/hof/pack.hpp>
  13. #include <boost/hof/always.hpp>
  14. #include <boost/hof/detail/move.hpp>
  15. #include <boost/hof/detail/result_type.hpp>
  16. /// capture
  17. /// =======
  18. ///
  19. /// Description
  20. /// -----------
  21. ///
  22. /// The `capture` function decorator is used to capture values in a function.
  23. /// It provides more flexibility in capturing than the lambda capture list in
  24. /// C++. It provides a way to do move and perfect capturing. The values
  25. /// captured are prepended to the argument list of the function that will be
  26. /// called.
  27. ///
  28. /// Synopsis
  29. /// --------
  30. ///
  31. /// // Capture by decaying each value
  32. /// template<class... Ts>
  33. /// constexpr auto capture(Ts&&... xs);
  34. ///
  35. /// // Capture lvalues by reference and rvalue reference by reference
  36. /// template<class... Ts>
  37. /// constexpr auto capture_forward(Ts&&... xs);
  38. ///
  39. /// // Capture lvalues by reference and rvalues by value.
  40. /// template<class... Ts>
  41. /// constexpr auto capture_basic(Ts&&... xs);
  42. ///
  43. /// Semantics
  44. /// ---------
  45. ///
  46. /// assert(capture(xs...)(f)(ys...) == f(xs..., ys...));
  47. ///
  48. ///
  49. /// Example
  50. /// -------
  51. ///
  52. /// #include <boost/hof.hpp>
  53. /// #include <cassert>
  54. ///
  55. /// struct sum_f
  56. /// {
  57. /// template<class T, class U>
  58. /// T operator()(T x, U y) const
  59. /// {
  60. /// return x+y;
  61. /// }
  62. /// };
  63. ///
  64. /// int main() {
  65. /// auto add_one = boost::hof::capture(1)(sum_f());
  66. /// assert(add_one(2) == 3);
  67. /// }
  68. ///
  69. namespace boost { namespace hof {
  70. namespace detail {
  71. template<class F, class Pack>
  72. struct capture_invoke : detail::compressed_pair<detail::callable_base<F>, Pack>, detail::function_result_type<F>
  73. {
  74. typedef capture_invoke fit_rewritable1_tag;
  75. typedef detail::compressed_pair<detail::callable_base<F>, Pack> base;
  76. BOOST_HOF_INHERIT_CONSTRUCTOR(capture_invoke, base)
  77. template<class... Ts>
  78. constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const noexcept
  79. {
  80. return this->first(xs...);
  81. }
  82. template<class... Ts>
  83. constexpr const Pack& get_pack(Ts&&...xs) const noexcept
  84. {
  85. return this->second(xs...);
  86. }
  87. template<class Failure, class... Ts>
  88. struct unpack_capture_failure
  89. {
  90. template<class... Us>
  91. struct apply
  92. {
  93. typedef typename Failure::template of<Us..., Ts...> type;
  94. };
  95. };
  96. struct capture_failure
  97. {
  98. template<class Failure>
  99. struct apply
  100. {
  101. template<class... Ts>
  102. struct of
  103. : Pack::template apply<unpack_capture_failure<Failure, Ts...>>::type
  104. {};
  105. };
  106. };
  107. struct failure
  108. : failure_map<capture_failure, detail::callable_base<F>>
  109. {};
  110. BOOST_HOF_RETURNS_CLASS(capture_invoke);
  111. template<class... Ts>
  112. constexpr BOOST_HOF_SFINAE_RESULT
  113. (
  114. typename result_of<decltype(boost::hof::pack_join),
  115. id_<const Pack&>,
  116. result_of<decltype(boost::hof::pack_forward), id_<Ts>...>
  117. >::type,
  118. id_<detail::callable_base<F>&&>
  119. )
  120. operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
  121. (
  122. boost::hof::pack_join
  123. (
  124. BOOST_HOF_MANGLE_CAST(const Pack&)(BOOST_HOF_CONST_THIS->get_pack(xs...)),
  125. boost::hof::pack_forward(BOOST_HOF_FORWARD(Ts)(xs)...)
  126. )
  127. (BOOST_HOF_RETURNS_C_CAST(detail::callable_base<F>&&)(BOOST_HOF_CONST_THIS->base_function(xs...)))
  128. );
  129. };
  130. template<class Pack>
  131. struct capture_pack : Pack
  132. {
  133. BOOST_HOF_INHERIT_CONSTRUCTOR(capture_pack, Pack);
  134. BOOST_HOF_RETURNS_CLASS(capture_pack);
  135. // TODO: Should use rvalue ref qualifier
  136. template<class F>
  137. constexpr auto operator()(F f) const BOOST_HOF_SFINAE_RETURNS
  138. (
  139. capture_invoke<F, Pack>(BOOST_HOF_RETURNS_STATIC_CAST(F&&)(f),
  140. BOOST_HOF_RETURNS_C_CAST(Pack&&)(
  141. BOOST_HOF_RETURNS_STATIC_CAST(const Pack&)(*boost::hof::always(BOOST_HOF_CONST_THIS)(f))
  142. )
  143. )
  144. );
  145. };
  146. struct make_capture_pack_f
  147. {
  148. template<class Pack>
  149. constexpr capture_pack<Pack> operator()(Pack p) const
  150. BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(capture_pack<Pack>, Pack&&)
  151. {
  152. return capture_pack<Pack>(static_cast<Pack&&>(p));
  153. }
  154. };
  155. template<class F>
  156. struct capture_f
  157. {
  158. template<class... Ts>
  159. constexpr auto operator()(Ts&&... xs) const BOOST_HOF_RETURNS
  160. (
  161. BOOST_HOF_RETURNS_CONSTRUCT(make_capture_pack_f)()(BOOST_HOF_RETURNS_CONSTRUCT(F)()(BOOST_HOF_FORWARD(Ts)(xs)...))
  162. );
  163. };
  164. }
  165. BOOST_HOF_DECLARE_STATIC_VAR(capture_basic, detail::capture_f<detail::pack_basic_f>);
  166. BOOST_HOF_DECLARE_STATIC_VAR(capture_forward, detail::capture_f<detail::pack_forward_f>);
  167. BOOST_HOF_DECLARE_STATIC_VAR(capture, detail::capture_f<detail::pack_f>);
  168. }} // namespace boost::hof
  169. #endif