/*! @file Defines `boost::hana::capture`. @copyright Louis Dionne 2013-2017 Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) */ #ifndef BOOST_HANA_FUNCTIONAL_CAPTURE_HPP #define BOOST_HANA_FUNCTIONAL_CAPTURE_HPP #include #include #include #include #include #include namespace boost { namespace hana { //! @ingroup group-functional //! Create a function capturing the given variables. //! //! Given 0 or more variables, `capture` creates a closure that can be //! used to partially apply a function. This is very similar to `partial`, //! except that `capture` allows the partially applied function to be //! specified later. Specifically, `capture(vars...)` is a function object //! taking a function `f` and returning `f` partially applied to `vars...`. //! In other words, //! @code //! capture(vars...)(f)(args...) == f(vars..., args...) //! @endcode //! //! @note //! The arity of `f` must match the total number of arguments passed to //! it, i.e. `sizeof...(vars) + sizeof...(args)`. //! //! //! Example //! ------- //! @include example/functional/capture.cpp #ifdef BOOST_HANA_DOXYGEN_INVOKED constexpr auto capture = [](auto&& ...variables) { return [perfect-capture](auto&& f) { return [perfect-capture](auto&& ...args) -> decltype(auto) { return forwarded(f)(forwarded(variables)..., forwarded(args)...); }; }; }; #else namespace detail { template constexpr auto apply_capture(F&& f, Closure&& closure, std::index_sequence) { return hana::partial(static_cast(f), hana::at_c(static_cast(closure).storage_)... ); } } template struct capture_t; struct make_capture_t { struct secret { }; template constexpr capture_t::type...> operator()(X&& ...x) const { return {secret{}, static_cast(x)...}; } }; template struct capture_t { template constexpr capture_t(make_capture_t::secret, Y&& ...y) : storage_{static_cast(y)...} { } basic_tuple storage_; template constexpr auto operator()(F&& f) const& { return detail::apply_capture( static_cast(f), *this, std::make_index_sequence{} ); } template constexpr auto operator()(F&& f) & { return detail::apply_capture( static_cast(f), *this, std::make_index_sequence{} ); } template constexpr auto operator()(F&& f) && { return detail::apply_capture( static_cast(f), static_cast(*this), std::make_index_sequence{} ); } }; BOOST_HANA_INLINE_VARIABLE constexpr make_capture_t capture{}; #endif }} // end namespace boost::hana #endif // !BOOST_HANA_FUNCTIONAL_CAPTURE_HPP