Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:43:50

0001 /*=============================================================================
0002     Copyright (c) 2015 Paul Fultz II
0003     capture.h
0004     Distributed under the Boost Software License, Version 1.0. (See accompanying
0005     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 ==============================================================================*/
0007 
0008 #ifndef BOOST_HOF_GUARD_CAPTURE_H
0009 #define BOOST_HOF_GUARD_CAPTURE_H
0010 
0011 #include <boost/hof/detail/callable_base.hpp>
0012 #include <boost/hof/detail/compressed_pair.hpp>
0013 #include <boost/hof/reveal.hpp>
0014 #include <boost/hof/pack.hpp>
0015 #include <boost/hof/always.hpp>
0016 #include <boost/hof/detail/move.hpp>
0017 #include <boost/hof/detail/result_type.hpp>
0018 
0019 /// capture
0020 /// =======
0021 /// 
0022 /// Description
0023 /// -----------
0024 /// 
0025 /// The `capture` function decorator is used to capture values in a function.
0026 /// It provides more flexibility in capturing than the lambda capture list in
0027 /// C++. It provides a way to do move and perfect capturing. The values
0028 /// captured are prepended to the argument list of the function that will be
0029 /// called.
0030 /// 
0031 /// Synopsis
0032 /// --------
0033 /// 
0034 ///     // Capture by decaying each value
0035 ///     template<class... Ts>
0036 ///     constexpr auto capture(Ts&&... xs);
0037 /// 
0038 ///     // Capture lvalues by reference and rvalue reference by reference
0039 ///     template<class... Ts>
0040 ///     constexpr auto capture_forward(Ts&&... xs);
0041 /// 
0042 ///     // Capture lvalues by reference and rvalues by value.
0043 ///     template<class... Ts>
0044 ///     constexpr auto capture_basic(Ts&&... xs);
0045 /// 
0046 /// Semantics
0047 /// ---------
0048 /// 
0049 ///     assert(capture(xs...)(f)(ys...) == f(xs..., ys...));
0050 /// 
0051 /// 
0052 /// Example
0053 /// -------
0054 /// 
0055 ///     #include <boost/hof.hpp>
0056 ///     #include <cassert>
0057 /// 
0058 ///     struct sum_f
0059 ///     {
0060 ///         template<class T, class U>
0061 ///         T operator()(T x, U y) const
0062 ///         {
0063 ///             return x+y;
0064 ///         }
0065 ///     };
0066 /// 
0067 ///     int main() {
0068 ///         auto add_one = boost::hof::capture(1)(sum_f());
0069 ///         assert(add_one(2) == 3);
0070 ///     }
0071 /// 
0072 
0073 namespace boost { namespace hof {
0074 
0075 namespace detail {
0076 
0077 template<class F, class Pack>
0078 struct capture_invoke : detail::compressed_pair<detail::callable_base<F>, Pack>, detail::function_result_type<F>
0079 {
0080     typedef capture_invoke fit_rewritable1_tag;
0081     typedef detail::compressed_pair<detail::callable_base<F>, Pack> base;
0082     BOOST_HOF_INHERIT_CONSTRUCTOR(capture_invoke, base)
0083     template<class... Ts>
0084     constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const noexcept
0085     {
0086         return this->first(xs...);
0087     }
0088 
0089     template<class... Ts>
0090     constexpr const Pack& get_pack(Ts&&...xs) const noexcept
0091     {
0092         return this->second(xs...);
0093     }
0094 
0095     template<class Failure, class... Ts>
0096     struct unpack_capture_failure
0097     {
0098         template<class... Us>
0099         struct apply
0100         {
0101             typedef typename Failure::template of<Us..., Ts...> type;
0102         };
0103     };
0104 
0105     struct capture_failure
0106     {
0107         template<class Failure>
0108         struct apply
0109         {
0110             template<class... Ts>
0111             struct of
0112             : Pack::template apply<unpack_capture_failure<Failure, Ts...>>::type
0113             {};
0114         };
0115     };
0116 
0117     struct failure
0118     : failure_map<capture_failure, detail::callable_base<F>>
0119     {};
0120 
0121     BOOST_HOF_RETURNS_CLASS(capture_invoke);
0122 
0123     template<class... Ts>
0124     constexpr BOOST_HOF_SFINAE_RESULT
0125     (
0126         typename result_of<decltype(boost::hof::pack_join), 
0127             id_<const Pack&>, 
0128             result_of<decltype(boost::hof::pack_forward), id_<Ts>...> 
0129         >::type,
0130         id_<detail::callable_base<F>&&>
0131     ) 
0132     operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
0133     (
0134         boost::hof::pack_join
0135         (
0136             BOOST_HOF_MANGLE_CAST(const Pack&)(BOOST_HOF_CONST_THIS->get_pack(xs...)), 
0137             boost::hof::pack_forward(BOOST_HOF_FORWARD(Ts)(xs)...)
0138         )
0139         (BOOST_HOF_RETURNS_C_CAST(detail::callable_base<F>&&)(BOOST_HOF_CONST_THIS->base_function(xs...)))
0140     );
0141 };
0142 
0143 template<class Pack>
0144 struct capture_pack : Pack
0145 {
0146     BOOST_HOF_INHERIT_CONSTRUCTOR(capture_pack, Pack);
0147 
0148     BOOST_HOF_RETURNS_CLASS(capture_pack);
0149 
0150     // TODO: Should use rvalue ref qualifier
0151     template<class F>
0152     constexpr auto operator()(F f) const BOOST_HOF_SFINAE_RETURNS
0153     (
0154         capture_invoke<F, Pack>(BOOST_HOF_RETURNS_STATIC_CAST(F&&)(f), 
0155             BOOST_HOF_RETURNS_C_CAST(Pack&&)(
0156                 BOOST_HOF_RETURNS_STATIC_CAST(const Pack&)(*boost::hof::always(BOOST_HOF_CONST_THIS)(f))
0157             )
0158         )
0159     );
0160 };
0161 
0162 struct make_capture_pack_f
0163 {
0164     template<class Pack>
0165     constexpr capture_pack<Pack> operator()(Pack p) const
0166     BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(capture_pack<Pack>, Pack&&)
0167     {
0168         return capture_pack<Pack>(static_cast<Pack&&>(p));
0169     }
0170 };
0171 
0172 template<class F>
0173 struct capture_f
0174 {
0175     template<class... Ts>
0176     constexpr auto operator()(Ts&&... xs) const BOOST_HOF_RETURNS
0177     (
0178         BOOST_HOF_RETURNS_CONSTRUCT(make_capture_pack_f)()(BOOST_HOF_RETURNS_CONSTRUCT(F)()(BOOST_HOF_FORWARD(Ts)(xs)...))
0179     );
0180 };
0181 }
0182 
0183 BOOST_HOF_DECLARE_STATIC_VAR(capture_basic, detail::capture_f<detail::pack_basic_f>);
0184 BOOST_HOF_DECLARE_STATIC_VAR(capture_forward, detail::capture_f<detail::pack_forward_f>);
0185 BOOST_HOF_DECLARE_STATIC_VAR(capture, detail::capture_f<detail::pack_f>);
0186 
0187 }} // namespace boost::hof
0188 
0189 #endif