Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:38:16

0001 /*=============================================================================
0002     Copyright (c) 2014 Paul Fultz II
0003     proj.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_FUNCTION_ON_H
0009 #define BOOST_HOF_GUARD_FUNCTION_ON_H
0010 
0011 /// proj
0012 /// ====
0013 /// 
0014 /// Description
0015 /// -----------
0016 /// 
0017 /// The `proj` function adaptor applies a projection onto the parameters of
0018 /// another function. This is useful, for example, to define a function for
0019 /// sorting such that the ordering is based off of the value of one of its
0020 /// member fields. 
0021 /// 
0022 /// Also, if just a projection is given, then the projection will be called
0023 /// for each of its arguments.
0024 /// 
0025 /// Note: All projections are always evaluated in order from left-to-right.
0026 /// 
0027 /// Synopsis
0028 /// --------
0029 /// 
0030 ///     template<class Projection, class F>
0031 ///     constexpr proj_adaptor<Projection, F> proj(Projection p, F f);
0032 /// 
0033 ///     template<class Projection>
0034 ///     constexpr proj_adaptor<Projection> proj(Projection p);
0035 /// 
0036 /// Semantics
0037 /// ---------
0038 /// 
0039 ///     assert(proj(p, f)(xs...) == f(p(xs)...));
0040 ///     assert(proj(p)(xs...) == p(xs)...);
0041 /// 
0042 /// Requirements
0043 /// ------------
0044 /// 
0045 /// Projection must be:
0046 /// 
0047 /// * [UnaryInvocable](UnaryInvocable)
0048 /// * MoveConstructible
0049 /// 
0050 /// F must be:
0051 /// 
0052 /// * [ConstInvocable](ConstInvocable)
0053 /// * MoveConstructible
0054 /// 
0055 /// Example
0056 /// -------
0057 /// 
0058 ///     #include <boost/hof.hpp>
0059 ///     #include <cassert>
0060 ///     using namespace boost::hof;
0061 /// 
0062 ///     struct foo
0063 ///     {
0064 ///         foo(int x_) : x(x_)
0065 ///         {}
0066 ///         int x;
0067 ///     };
0068 /// 
0069 ///     int main() {
0070 ///         assert(boost::hof::proj(&foo::x, _ + _)(foo(1), foo(2)) == 3);
0071 ///     }
0072 /// 
0073 /// References
0074 /// ----------
0075 /// 
0076 /// * [Projections](Projections)
0077 /// * [Variadic print](<Variadic print>)
0078 /// 
0079 
0080 
0081 
0082 #include <utility>
0083 #include <boost/hof/always.hpp>
0084 #include <boost/hof/detail/callable_base.hpp>
0085 #include <boost/hof/detail/result_of.hpp>
0086 #include <boost/hof/detail/move.hpp>
0087 #include <boost/hof/detail/make.hpp>
0088 #include <boost/hof/detail/static_const_var.hpp>
0089 #include <boost/hof/detail/compressed_pair.hpp>
0090 #include <boost/hof/detail/result_type.hpp>
0091 #include <boost/hof/apply_eval.hpp>
0092 
0093 namespace boost { namespace hof {
0094 
0095 namespace detail {
0096 
0097 template<class T, class Projection>
0098 struct project_eval
0099 {
0100     T&& x;
0101     const Projection& p;
0102 
0103     template<class X, class P>
0104     constexpr project_eval(X&& xp, const P& pp) : x(BOOST_HOF_FORWARD(X)(xp)), p(pp)
0105     {}
0106 
0107     constexpr auto operator()() const BOOST_HOF_RETURNS
0108     (p(BOOST_HOF_FORWARD(T)(x)));
0109 };
0110 
0111 template<class T, class Projection>
0112 constexpr project_eval<T, Projection> make_project_eval(T&& x, const Projection& p)
0113 {
0114     return project_eval<T, Projection>(BOOST_HOF_FORWARD(T)(x), p);
0115 }
0116 
0117 template<class T, class Projection>
0118 struct project_void_eval
0119 {
0120     T&& x;
0121     const Projection& p;
0122 
0123     template<class X, class P>
0124     constexpr project_void_eval(X&& xp, const P& pp) : x(BOOST_HOF_FORWARD(X)(xp)), p(pp)
0125     {}
0126 
0127     struct void_ {};
0128 
0129     constexpr void_ operator()() const
0130     {
0131         return p(BOOST_HOF_FORWARD(T)(x)), void_();
0132     }
0133 };
0134 
0135 template<class T, class Projection>
0136 constexpr project_void_eval<T, Projection> make_project_void_eval(T&& x, const Projection& p)
0137 {
0138     return project_void_eval<T, Projection>(BOOST_HOF_FORWARD(T)(x), p);
0139 }
0140 
0141 template<class Projection, class F, class... Ts, 
0142     class R=decltype(
0143         std::declval<const F&>()(std::declval<const Projection&>()(std::declval<Ts>())...)
0144     )>
0145 constexpr R by_eval(const Projection& p, const F& f, Ts&&... xs)
0146 {
0147     return boost::hof::apply_eval(f, make_project_eval(BOOST_HOF_FORWARD(Ts)(xs), p)...);
0148 }
0149 
0150 #if BOOST_HOF_NO_ORDERED_BRACE_INIT
0151 #define BOOST_HOF_BY_VOID_RETURN BOOST_HOF_ALWAYS_VOID_RETURN
0152 #else
0153 #if BOOST_HOF_NO_CONSTEXPR_VOID
0154 #define BOOST_HOF_BY_VOID_RETURN boost::hof::detail::swallow
0155 #else
0156 #define BOOST_HOF_BY_VOID_RETURN void
0157 #endif
0158 #endif
0159 
0160 template<class Projection, class... Ts>
0161 constexpr BOOST_HOF_ALWAYS_VOID_RETURN by_void_eval(const Projection& p, Ts&&... xs)
0162 {
0163     return boost::hof::apply_eval(boost::hof::always(), boost::hof::detail::make_project_void_eval(BOOST_HOF_FORWARD(Ts)(xs), p)...);
0164 }
0165 
0166 struct swallow
0167 {
0168     template<class... Ts>
0169     constexpr swallow(Ts&&...)
0170     {}
0171 };
0172 
0173 }
0174 
0175 template<class Projection, class F=void>
0176 struct proj_adaptor;
0177 
0178 template<class Projection, class F>
0179 struct proj_adaptor : detail::compressed_pair<detail::callable_base<Projection>, detail::callable_base<F>>, detail::function_result_type<F>
0180 {
0181     typedef proj_adaptor fit_rewritable_tag;
0182     typedef detail::compressed_pair<detail::callable_base<Projection>, detail::callable_base<F>> base;
0183     template<class... Ts>
0184     constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const
0185     {
0186         return this->second(xs...);;
0187     }
0188 
0189     template<class... Ts>
0190     constexpr const detail::callable_base<Projection>& base_projection(Ts&&... xs) const
0191     {
0192         return this->first(xs...);
0193     }
0194 
0195     struct by_failure
0196     {
0197         template<class Failure>
0198         struct apply
0199         {
0200             template<class... Ts>
0201             struct of
0202             : Failure::template of<decltype(std::declval<detail::callable_base<Projection>>()(std::declval<Ts>()))...>
0203             {};
0204         };
0205     };
0206 
0207     struct failure
0208     : failure_map<by_failure, detail::callable_base<F>>
0209     {};
0210 
0211     BOOST_HOF_INHERIT_CONSTRUCTOR(proj_adaptor, base)
0212 
0213     BOOST_HOF_RETURNS_CLASS(proj_adaptor);
0214 
0215     template<class... Ts>
0216     constexpr BOOST_HOF_SFINAE_RESULT(const detail::callable_base<F>&, result_of<const detail::callable_base<Projection>&, id_<Ts>>...) 
0217     operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
0218     (
0219         boost::hof::detail::by_eval(
0220             BOOST_HOF_MANGLE_CAST(const detail::callable_base<Projection>&)(BOOST_HOF_CONST_THIS->base_projection(xs...)),
0221             BOOST_HOF_MANGLE_CAST(const detail::callable_base<F>&)(BOOST_HOF_CONST_THIS->base_function(xs...)),
0222             BOOST_HOF_FORWARD(Ts)(xs)...
0223         )
0224     );
0225 };
0226 
0227 template<class Projection>
0228 struct proj_adaptor<Projection, void> : detail::callable_base<Projection>
0229 {
0230     typedef proj_adaptor fit_rewritable1_tag;
0231     template<class... Ts>
0232     constexpr const detail::callable_base<Projection>& base_projection(Ts&&... xs) const
0233     {
0234         return boost::hof::always_ref(*this)(xs...);
0235     }
0236 
0237     BOOST_HOF_INHERIT_DEFAULT(proj_adaptor, detail::callable_base<Projection>)
0238 
0239     template<class P, BOOST_HOF_ENABLE_IF_CONVERTIBLE(P, detail::callable_base<Projection>)>
0240     constexpr proj_adaptor(P&& p) 
0241     : detail::callable_base<Projection>(BOOST_HOF_FORWARD(P)(p))
0242     {}
0243 
0244     BOOST_HOF_RETURNS_CLASS(proj_adaptor);
0245 
0246     template<class... Ts, class=detail::holder<decltype(std::declval<Projection>()(std::declval<Ts>()))...>>
0247     constexpr BOOST_HOF_BY_VOID_RETURN operator()(Ts&&... xs) const 
0248     {
0249 #if BOOST_HOF_NO_ORDERED_BRACE_INIT
0250         return boost::hof::detail::by_void_eval(this->base_projection(xs...), BOOST_HOF_FORWARD(Ts)(xs)...);
0251 #else
0252 #if BOOST_HOF_NO_CONSTEXPR_VOID
0253         return
0254 #endif
0255         boost::hof::detail::swallow{
0256             (this->base_projection(xs...)(BOOST_HOF_FORWARD(Ts)(xs)), 0)...
0257         };
0258 #endif
0259     }
0260 };
0261 
0262 BOOST_HOF_DECLARE_STATIC_VAR(proj, detail::make<proj_adaptor>);
0263 
0264 }} // namespace boost::hof
0265 #endif