File indexing completed on 2025-01-18 09:38:15
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_HOF_GUARD_FUNCTION_LAZY_H
0009 #define BOOST_HOF_GUARD_FUNCTION_LAZY_H
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069 #include <boost/hof/arg.hpp>
0070 #include <boost/hof/first_of.hpp>
0071 #include <boost/hof/always.hpp>
0072 #include <boost/hof/static.hpp>
0073 #include <boost/hof/detail/delegate.hpp>
0074 #include <boost/hof/detail/compressed_pair.hpp>
0075 #include <boost/hof/pack.hpp>
0076 #include <boost/hof/detail/make.hpp>
0077 #include <boost/hof/detail/static_const_var.hpp>
0078 #include <functional>
0079 #include <type_traits>
0080
0081 namespace boost { namespace hof {
0082
0083 namespace detail {
0084
0085 struct placeholder_transformer
0086 {
0087 template<class T, typename std::enable_if<(std::is_placeholder<T>::value > 0), int>::type = 0>
0088 constexpr detail::make_args_f<std::size_t, std::is_placeholder<T>::value> operator()(const T&) const noexcept
0089 {
0090 return {};
0091 }
0092 };
0093
0094 struct bind_transformer
0095 {
0096 template<class T, typename std::enable_if<std::is_bind_expression<T>::value, int>::type = 0>
0097 constexpr const T& operator()(const T& x) const noexcept
0098 {
0099 return x;
0100 }
0101 };
0102
0103 struct ref_transformer
0104 {
0105 template<class T>
0106 constexpr auto operator()(std::reference_wrapper<T> x) const
0107 BOOST_HOF_SFINAE_RETURNS(boost::hof::always_ref(x.get()));
0108 };
0109
0110 struct id_transformer
0111 {
0112 template<class T>
0113 constexpr auto operator()(T&& x) const
0114 BOOST_HOF_SFINAE_RETURNS(always_detail::always_base<T>(BOOST_HOF_FORWARD(T)(x)));
0115 };
0116
0117 BOOST_HOF_DECLARE_STATIC_VAR(pick_transformer, first_of_adaptor<placeholder_transformer, bind_transformer, ref_transformer, id_transformer>);
0118
0119 template<class T, class Pack>
0120 constexpr auto lazy_transform(T&& x, const Pack& p) BOOST_HOF_RETURNS
0121 (
0122 p(boost::hof::detail::pick_transformer(BOOST_HOF_FORWARD(T)(x)))
0123 );
0124
0125 template<class F, class Pack>
0126 struct lazy_unpack
0127 {
0128 const F& f;
0129 const Pack& p;
0130
0131 constexpr lazy_unpack(const F& fp, const Pack& pp) noexcept
0132 : f(fp), p(pp)
0133 {}
0134
0135 template<class... Ts>
0136 constexpr auto operator()(Ts&&... xs) const BOOST_HOF_RETURNS
0137 (
0138 f(lazy_transform(BOOST_HOF_FORWARD(Ts)(xs), p)...)
0139 );
0140 };
0141
0142 template<class F, class Pack>
0143 constexpr lazy_unpack<F, Pack> make_lazy_unpack(const F& f, const Pack& p) noexcept
0144 {
0145 return lazy_unpack<F, Pack>(f, p);
0146 }
0147
0148 template<class F, class Pack>
0149 struct lazy_invoker
0150 : detail::compressed_pair<F, Pack>
0151 {
0152 typedef detail::compressed_pair<F, Pack> base_type;
0153 typedef lazy_invoker fit_rewritable1_tag;
0154
0155 #ifdef _MSC_VER
0156 BOOST_HOF_INHERIT_CONSTRUCTOR(lazy_invoker, base_type)
0157 #else
0158 BOOST_HOF_INHERIT_DEFAULT_EMPTY(lazy_invoker, base_type)
0159
0160 template<class X, class Y,
0161 BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(base_type, X&&, Y&&)
0162 >
0163 constexpr lazy_invoker(X&& x, Y&& y)
0164 BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(base_type, X&&, Y&&)
0165 : base_type(BOOST_HOF_FORWARD(X)(x), BOOST_HOF_FORWARD(Y)(y))
0166 {}
0167 #endif
0168
0169 template<class... Ts>
0170 constexpr const F& base_function(Ts&&... xs) const noexcept
0171 {
0172 return this->first(xs...);
0173 }
0174
0175 template<class... Ts>
0176 constexpr const Pack& get_pack(Ts&&... xs) const noexcept
0177 {
0178 return this->second(xs...);
0179 }
0180
0181 BOOST_HOF_RETURNS_CLASS(lazy_invoker);
0182
0183 template<class... Ts>
0184 constexpr auto operator()(Ts&&... xs) const BOOST_HOF_RETURNS
0185 (
0186 BOOST_HOF_MANGLE_CAST(const Pack&)(BOOST_HOF_CONST_THIS->get_pack(xs...))(
0187 boost::hof::detail::make_lazy_unpack(
0188 BOOST_HOF_MANGLE_CAST(const F&)(BOOST_HOF_CONST_THIS->base_function(xs...)),
0189 boost::hof::pack_forward(BOOST_HOF_FORWARD(Ts)(xs)...)
0190 )
0191 )
0192 );
0193 };
0194
0195 template<class F, class Pack>
0196 constexpr lazy_invoker<F, Pack> make_lazy_invoker(F f, Pack pack)
0197 BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(lazy_invoker<F, Pack>, F&&, Pack&&)
0198 {
0199 return lazy_invoker<F, Pack>(static_cast<F&&>(f), static_cast<Pack&&>(pack));
0200 }
0201
0202 template<class F>
0203 struct lazy_nullary_invoker : F
0204 {
0205 BOOST_HOF_INHERIT_CONSTRUCTOR(lazy_nullary_invoker, F);
0206
0207 template<class... Ts>
0208 constexpr const F& base_function(Ts&&... xs) const noexcept
0209 {
0210 return boost::hof::always_ref(*this)(xs...);
0211 }
0212
0213 BOOST_HOF_RETURNS_CLASS(lazy_nullary_invoker);
0214
0215 template<class... Ts>
0216 constexpr auto operator()(Ts&&... xs) const BOOST_HOF_RETURNS
0217 (
0218 BOOST_HOF_MANGLE_CAST(const F&)(BOOST_HOF_CONST_THIS->base_function(xs...))()
0219 );
0220 };
0221
0222 template<class F>
0223 constexpr lazy_nullary_invoker<F> make_lazy_nullary_invoker(F f)
0224 BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(lazy_nullary_invoker<F>, F&&)
0225 {
0226 return lazy_nullary_invoker<F>(static_cast<F&&>(f));
0227 }
0228 }
0229
0230
0231 template<class F>
0232 struct lazy_adaptor : detail::callable_base<F>
0233 {
0234 BOOST_HOF_INHERIT_CONSTRUCTOR(lazy_adaptor, detail::callable_base<F>);
0235
0236 template<class... Ts>
0237 constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const noexcept
0238 {
0239 return boost::hof::always_ref(*this)(xs...);
0240 }
0241
0242 BOOST_HOF_RETURNS_CLASS(lazy_adaptor);
0243
0244 template<class T, class... Ts>
0245 constexpr auto operator()(T x, Ts... xs) const BOOST_HOF_RETURNS
0246 (
0247 boost::hof::detail::make_lazy_invoker(BOOST_HOF_RETURNS_C_CAST(detail::callable_base<F>&&)(BOOST_HOF_CONST_THIS->base_function(x, xs...)),
0248 boost::hof::pack_basic(BOOST_HOF_RETURNS_STATIC_CAST(T&&)(x), BOOST_HOF_RETURNS_STATIC_CAST(Ts&&)(xs)...))
0249 );
0250
0251
0252 template<class Unused=int>
0253 constexpr detail::lazy_nullary_invoker<F> operator()() const
0254 BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(
0255 boost::hof::detail::make_lazy_nullary_invoker(BOOST_HOF_RETURNS_C_CAST(detail::callable_base<F>&&)(
0256 BOOST_HOF_CONST_THIS->base_function(BOOST_HOF_RETURNS_CONSTRUCT(Unused)())
0257 ))
0258 )
0259 {
0260 return boost::hof::detail::make_lazy_nullary_invoker((detail::callable_base<F>&&)(
0261 this->base_function(Unused())
0262 ));
0263 }
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281 };
0282
0283 BOOST_HOF_DECLARE_STATIC_VAR(lazy, detail::make<lazy_adaptor>);
0284
0285 }}
0286
0287 namespace std {
0288 template<class F, class Pack>
0289 struct is_bind_expression<boost::hof::detail::lazy_invoker<F, Pack>>
0290 : std::true_type
0291 {};
0292
0293 template<class F>
0294 struct is_bind_expression<boost::hof::detail::lazy_nullary_invoker<F>>
0295 : std::true_type
0296 {};
0297 }
0298
0299 #endif