Back to home page

EIC code displayed by LXR

 
 

    


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

0001 /*=============================================================================
0002     Copyright (c) 2015 Paul Fultz II
0003     apply.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_APPLY_H
0009 #define BOOST_HOF_GUARD_APPLY_H
0010 
0011 /// apply
0012 /// =====
0013 /// 
0014 /// Description
0015 /// -----------
0016 /// 
0017 /// The `apply` function calls the function given to it with its arguments.
0018 /// 
0019 /// Synopsis
0020 /// --------
0021 /// 
0022 ///     template<class F, class... Ts>
0023 ///     constexpr auto apply(F&& f, Ts&&... xs);
0024 /// 
0025 /// Semantics
0026 /// ---------
0027 /// 
0028 ///     assert(apply(f)(xs...) == f(xs...));
0029 ///     assert(fold(apply, f)(x, y, z) == f(x)(y)(z));
0030 /// 
0031 /// Requirements
0032 /// ------------
0033 /// 
0034 /// F must be:
0035 /// 
0036 /// * [Invocable](Invocable)
0037 /// 
0038 /// Example
0039 /// -------
0040 /// 
0041 ///     #include <boost/hof.hpp>
0042 ///     #include <cassert>
0043 /// 
0044 ///     struct sum_f
0045 ///     {
0046 ///         template<class T, class U>
0047 ///         T operator()(T x, U y) const
0048 ///         {
0049 ///             return x+y;
0050 ///         }
0051 ///     };
0052 /// 
0053 ///     int main() {
0054 ///         assert(boost::hof::apply(sum_f(), 1, 2) == 3);
0055 ///     }
0056 /// 
0057 
0058 #include <boost/hof/detail/result_of.hpp>
0059 #include <boost/hof/detail/forward.hpp>
0060 #include <boost/hof/detail/static_const_var.hpp>
0061 
0062 #ifdef _MSC_VER
0063 #pragma warning(push)
0064 #pragma warning(disable: 4003)
0065 #endif
0066 
0067 #define BOOST_HOF_DETAIL_FOREACH_QUAL(m, data) \
0068     m(, data) \
0069     m(const, data) \
0070     m(volatile, data) \
0071     m(const volatile, data)
0072 
0073 namespace boost { namespace hof {
0074 
0075 namespace detail {
0076 #if BOOST_HOF_HAS_MANUAL_DEDUCTION || BOOST_HOF_NO_EXPRESSION_SFINAE
0077 struct apply_mem_fn
0078 {
0079     template<class...>
0080     struct convertible_args;
0081 
0082     template<class T, class U, class=void>
0083     struct is_convertible_args
0084     : std::false_type
0085     {};
0086 
0087     template<class... Ts, class... Us>
0088     struct is_convertible_args<
0089         convertible_args<Ts...>, 
0090         convertible_args<Us...>, 
0091         typename std::enable_if<(
0092             sizeof...(Ts) == sizeof...(Us)
0093         )>::type
0094     >
0095     : and_<std::is_convertible<Ts, Us>...>
0096     {};
0097 
0098     template<class From, class To>
0099     struct is_compatible
0100     : std::is_convertible<
0101         typename std::add_pointer<typename std::remove_reference<From>::type>::type,
0102         typename std::add_pointer<typename std::remove_reference<To>::type>::type
0103     >
0104     {};
0105 
0106 #define BOOST_HOF_APPLY_MEM_FN_CALL(cv, data) \
0107     template <class R, class Base, class Derived, class... Ts, class... Us, class=typename std::enable_if<and_< \
0108         is_compatible<Derived, cv Base>, \
0109         is_convertible_args<convertible_args<Us...>, convertible_args<Ts...>> \
0110     >::value>::type> \
0111     constexpr R operator()(R (Base::*mf)(Ts...) cv, Derived&& ref, Us &&... xs) const \
0112     BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT((BOOST_HOF_FORWARD(Derived)(ref).*mf)(BOOST_HOF_FORWARD(Us)(xs)...)) \
0113     { \
0114         return (BOOST_HOF_FORWARD(Derived)(ref).*mf)(BOOST_HOF_FORWARD(Us)(xs)...); \
0115     }
0116     BOOST_HOF_DETAIL_FOREACH_QUAL(BOOST_HOF_APPLY_MEM_FN_CALL, ~)
0117 };
0118 
0119 struct apply_mem_data
0120 {
0121     template<class T, class R>
0122     struct match_qualifier
0123     { typedef R type; };
0124 
0125 #define BOOST_HOF_APPLY_MEM_DATA_MATCH(cv, ref) \
0126     template<class T, class R> \
0127     struct match_qualifier<cv T ref, R> \
0128     : match_qualifier<T, cv R ref> \
0129     {};
0130 
0131     BOOST_HOF_DETAIL_FOREACH_QUAL(BOOST_HOF_APPLY_MEM_DATA_MATCH,&)
0132     BOOST_HOF_DETAIL_FOREACH_QUAL(BOOST_HOF_APPLY_MEM_DATA_MATCH,&&)
0133 
0134     template <class Base, class R, class Derived, class=typename std::enable_if<(
0135         std::is_base_of<Base, typename std::decay<Derived>::type>::value
0136     )>::type>
0137     constexpr typename match_qualifier<Derived, R>::type 
0138     operator()(R Base::*pmd, Derived&& ref) const noexcept
0139     {
0140         return BOOST_HOF_FORWARD(Derived)(ref).*pmd;
0141     }
0142 };
0143 
0144 template<class T, class U=decltype(*std::declval<T>())>
0145 struct apply_deref
0146 { typedef U type; };
0147 
0148 #endif
0149 
0150 struct apply_f
0151 {
0152 #if BOOST_HOF_HAS_MANUAL_DEDUCTION || BOOST_HOF_NO_EXPRESSION_SFINAE
0153     template<class F, class T, class... Ts, class=typename std::enable_if<(
0154         std::is_member_function_pointer<typename std::decay<F>::type>::value
0155     )>::type>
0156     constexpr BOOST_HOF_SFINAE_MANUAL_RESULT(apply_mem_fn, id_<F>, id_<T>, id_<Ts>...) 
0157     operator()(F&& f, T&& obj, Ts&&... xs) const BOOST_HOF_SFINAE_MANUAL_RETURNS
0158     (
0159         apply_mem_fn()(f, BOOST_HOF_FORWARD(T)(obj), BOOST_HOF_FORWARD(Ts)(xs)...)
0160     );
0161 
0162     template<class F, class T, class... Ts, class U=typename apply_deref<T>::type, class=typename std::enable_if<(
0163         std::is_member_function_pointer<typename std::decay<F>::type>::value
0164     )>::type>
0165     constexpr BOOST_HOF_SFINAE_MANUAL_RESULT(apply_mem_fn, id_<F>, id_<U>, id_<Ts>...) 
0166     operator()(F&& f, T&& obj, Ts&&... xs) const BOOST_HOF_SFINAE_MANUAL_RETURNS
0167     (
0168         apply_mem_fn()(f, *BOOST_HOF_FORWARD(T)(obj), BOOST_HOF_FORWARD(Ts)(xs)...)
0169     );
0170 
0171     template<class F, class T, class... Ts, class=typename std::enable_if<(
0172         std::is_member_function_pointer<typename std::decay<F>::type>::value
0173     )>::type>
0174     constexpr BOOST_HOF_SFINAE_MANUAL_RESULT(apply_mem_fn, id_<F>, id_<T&>, id_<Ts>...) 
0175     operator()(F&& f, const std::reference_wrapper<T>& ref, Ts&&... xs) const BOOST_HOF_SFINAE_MANUAL_RETURNS
0176     (
0177         apply_mem_fn()(f, ref.get(), BOOST_HOF_FORWARD(Ts)(xs)...)
0178     );
0179 
0180     template<class F, class T, class=typename std::enable_if<(
0181         std::is_member_object_pointer<typename std::decay<F>::type>::value
0182     )>::type>
0183     constexpr BOOST_HOF_SFINAE_MANUAL_RESULT(apply_mem_data, id_<F>, id_<T>) 
0184     operator()(F&& f, T&& obj) const BOOST_HOF_SFINAE_MANUAL_RETURNS
0185     (
0186         apply_mem_data()(f, BOOST_HOF_FORWARD(T)(obj))
0187     );
0188 
0189     template<class F, class T, class U=typename apply_deref<T>::type, class=typename std::enable_if<(
0190         std::is_member_object_pointer<typename std::decay<F>::type>::value
0191     )>::type>
0192     constexpr BOOST_HOF_SFINAE_MANUAL_RESULT(apply_mem_data, id_<F>, id_<U>) 
0193     operator()(F&& f, T&& obj) const BOOST_HOF_SFINAE_MANUAL_RETURNS
0194     (
0195         apply_mem_data()(f, *BOOST_HOF_FORWARD(T)(obj))
0196     );
0197     
0198     template<class F, class T, class=typename std::enable_if<(
0199         std::is_member_object_pointer<typename std::decay<F>::type>::value
0200     )>::type>
0201     constexpr BOOST_HOF_SFINAE_MANUAL_RESULT(apply_mem_data, id_<F>, id_<T&>) 
0202     operator()(F&& f, const std::reference_wrapper<T>& ref) const BOOST_HOF_SFINAE_MANUAL_RETURNS
0203     (
0204         apply_mem_data()(f, ref.get())
0205     );
0206 
0207 #else
0208 
0209     template <class Base, class T, class Derived>
0210     constexpr auto operator()(T Base::*pmd, Derived&& ref) const
0211     BOOST_HOF_RETURNS(BOOST_HOF_FORWARD(Derived)(ref).*pmd);
0212      
0213     template <class PMD, class Pointer>
0214     constexpr auto operator()(PMD&& pmd, Pointer&& ptr) const
0215     BOOST_HOF_RETURNS((*BOOST_HOF_FORWARD(Pointer)(ptr)).*BOOST_HOF_FORWARD(PMD)(pmd));
0216 
0217     template <class Base, class T, class Derived>
0218     constexpr auto operator()(T Base::*pmd, const std::reference_wrapper<Derived>& ref) const
0219     BOOST_HOF_RETURNS(ref.get().*pmd);
0220      
0221     template <class Base, class T, class Derived, class... Args>
0222     constexpr auto operator()(T Base::*pmf, Derived&& ref, Args&&... args) const
0223     BOOST_HOF_RETURNS((BOOST_HOF_FORWARD(Derived)(ref).*pmf)(BOOST_HOF_FORWARD(Args)(args)...));
0224      
0225     template <class PMF, class Pointer, class... Args>
0226     constexpr auto operator()(PMF&& pmf, Pointer&& ptr, Args&&... args) const
0227     BOOST_HOF_RETURNS(((*BOOST_HOF_FORWARD(Pointer)(ptr)).*BOOST_HOF_FORWARD(PMF)(pmf))(BOOST_HOF_FORWARD(Args)(args)...));
0228 
0229     template <class Base, class T, class Derived, class... Args>
0230     constexpr auto operator()(T Base::*pmf, const std::reference_wrapper<Derived>& ref, Args&&... args) const
0231     BOOST_HOF_RETURNS((ref.get().*pmf)(BOOST_HOF_FORWARD(Args)(args)...));
0232 
0233 #endif
0234     template<class F, class... Ts>
0235     constexpr BOOST_HOF_SFINAE_MANUAL_RESULT(F, id_<Ts>...) 
0236     operator()(F&& f, Ts&&... xs) const BOOST_HOF_SFINAE_MANUAL_RETURNS
0237     (
0238         f(BOOST_HOF_FORWARD(Ts)(xs)...)
0239     );
0240 };
0241 
0242 }
0243 
0244 BOOST_HOF_DECLARE_STATIC_VAR(apply, detail::apply_f);
0245 
0246 }} // namespace boost::hof
0247 
0248 #ifdef _MSC_VER
0249 #pragma warning(pop)
0250 #endif
0251 
0252 #endif