Back to home page

EIC code displayed by LXR

 
 

    


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

0001 /*=============================================================================
0002     Copyright (c) 2015 Paul Fultz II
0003     lift.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_LIFT_H
0009 #define BOOST_HOF_GUARD_FUNCTION_LIFT_H
0010 
0011 /// BOOST_HOF_LIFT
0012 /// ========
0013 /// 
0014 /// Description
0015 /// -----------
0016 /// 
0017 /// The macros `BOOST_HOF_LIFT` and `BOOST_HOF_LIFT_CLASS` provide a lift operator that
0018 /// will wrap a template function in a function object so it can be passed to
0019 /// higher-order functions. The `BOOST_HOF_LIFT` macro will wrap the function using
0020 /// a generic lambda. As such, it will not preserve `constexpr`. The
0021 /// `BOOST_HOF_LIFT_CLASS` can be used to declare a class that will wrap function.
0022 /// This will preserve `constexpr` and it can be used on older compilers that
0023 /// don't support generic lambdas yet.
0024 /// 
0025 /// Limitation
0026 /// ----------
0027 /// 
0028 /// In C++14, `BOOST_HOF_LIFT` doesn't support `constexpr` due to using a generic
0029 /// lambda. Instead, `BOOST_HOF_LIFT_CLASS` can be used. In C++17, there is no such
0030 /// limitation.
0031 /// 
0032 /// Synopsis
0033 /// --------
0034 /// 
0035 ///     // Wrap the function in a generic lambda
0036 ///     #define BOOST_HOF_LIFT(...)
0037 /// 
0038 ///     // Declare a class named `name` that will forward to the function
0039 ///     #define BOOST_HOF_LIFT_CLASS(name, ...)
0040 /// 
0041 /// Example
0042 /// -------
0043 /// 
0044 ///     #include <boost/hof.hpp>
0045 ///     #include <cassert>
0046 ///     #include <algorithm>
0047 /// 
0048 ///     // Declare the class `max_f`
0049 ///     BOOST_HOF_LIFT_CLASS(max_f, std::max);
0050 /// 
0051 ///     int main() {
0052 ///         auto my_max = BOOST_HOF_LIFT(std::max);
0053 ///         assert(my_max(3, 4) == std::max(3, 4));
0054 ///         assert(max_f()(3, 4) == std::max(3, 4));
0055 ///     }
0056 /// 
0057 
0058 #include <boost/hof/detail/delegate.hpp>
0059 #include <boost/hof/returns.hpp>
0060 #include <boost/hof/lambda.hpp>
0061 #include <boost/hof/detail/forward.hpp>
0062 
0063 namespace boost { namespace hof { namespace detail {
0064 
0065 template<class F, class NoExcept>
0066 struct lift_noexcept : F
0067 {
0068     BOOST_HOF_INHERIT_CONSTRUCTOR(lift_noexcept, F);
0069 
0070     template<class... Ts>
0071     constexpr auto operator()(Ts&&... xs) const
0072     noexcept(decltype(std::declval<NoExcept>()(BOOST_HOF_FORWARD(Ts)(xs)...)){})
0073     -> decltype(std::declval<F>()(BOOST_HOF_FORWARD(Ts)(xs)...))
0074     { return F(*this)(BOOST_HOF_FORWARD(Ts)(xs)...);}
0075 };
0076 
0077 template<class F, class NoExcept>
0078 constexpr lift_noexcept<F, NoExcept> make_lift_noexcept(F f, NoExcept)
0079 {
0080     return {f};
0081 }
0082 
0083 }
0084 
0085 }} // namespace boost::hof
0086 
0087 #define BOOST_HOF_LIFT_IS_NOEXCEPT(...) std::integral_constant<bool, noexcept(decltype(__VA_ARGS__)(__VA_ARGS__))>{}
0088 
0089 #if defined (_MSC_VER)
0090 #define BOOST_HOF_LIFT(...) (BOOST_HOF_STATIC_LAMBDA { BOOST_HOF_LIFT_CLASS(fit_local_lift_t, __VA_ARGS__); return fit_local_lift_t(); }())
0091 #elif defined (__clang__)
0092 #define BOOST_HOF_LIFT(...) (boost::hof::detail::make_lift_noexcept( \
0093     BOOST_HOF_STATIC_LAMBDA(auto&&... xs) \
0094     -> decltype((__VA_ARGS__)(BOOST_HOF_FORWARD(decltype(xs))(xs)...)) \
0095     { return (__VA_ARGS__)(BOOST_HOF_FORWARD(decltype(xs))(xs)...); }, \
0096     BOOST_HOF_STATIC_LAMBDA(auto&&... xs) { return BOOST_HOF_LIFT_IS_NOEXCEPT((__VA_ARGS__)(BOOST_HOF_FORWARD(decltype(xs))(xs)...)); } \
0097 ))
0098 #else
0099 #define BOOST_HOF_LIFT(...) (BOOST_HOF_STATIC_LAMBDA(auto&&... xs) BOOST_HOF_RETURNS((__VA_ARGS__)(BOOST_HOF_FORWARD(decltype(xs))(xs)...)))
0100 #endif
0101 
0102 #define BOOST_HOF_LIFT_CLASS(name, ...) \
0103 struct name \
0104 { \
0105     template<class... Ts> \
0106     constexpr auto operator()(Ts&&... xs) const \
0107     BOOST_HOF_RETURNS((__VA_ARGS__)(BOOST_HOF_FORWARD(Ts)(xs)...)) \
0108 }
0109 
0110 #endif