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