Back to home page

EIC code displayed by LXR

 
 

    


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

0001 /*=============================================================================
0002     Copyright (c) 2014 Paul Fultz II
0003     lambda.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_LAMBDA_H
0009 #define BOOST_HOF_GUARD_FUNCTION_LAMBDA_H
0010 
0011 /// BOOST_HOF_STATIC_LAMBDA
0012 /// =================
0013 /// 
0014 /// Description
0015 /// -----------
0016 /// 
0017 /// The `BOOST_HOF_STATIC_LAMBDA` macro allows initializing non-capturing lambdas at
0018 /// compile-time in a `constexpr` expression.
0019 /// 
0020 /// Example
0021 /// -------
0022 /// 
0023 ///     #include <boost/hof.hpp>
0024 ///     #include <cassert>
0025 /// 
0026 ///     const constexpr auto add_one = BOOST_HOF_STATIC_LAMBDA(int x)
0027 ///     {
0028 ///         return x + 1;
0029 ///     };
0030 /// 
0031 ///     int main() {
0032 ///         assert(3 == add_one(2));
0033 ///     }
0034 /// 
0035 /// BOOST_HOF_STATIC_LAMBDA_FUNCTION
0036 /// ==========================
0037 /// 
0038 /// Description
0039 /// -----------
0040 /// 
0041 /// The `BOOST_HOF_STATIC_LAMBDA_FUNCTION` macro allows initializing a global
0042 /// function object that contains non-capturing lambdas. It also ensures that
0043 /// the global function object has a unique address across translation units.
0044 /// This helps prevent possible ODR-violations.
0045 ///
0046 /// By default, all functions defined with `BOOST_HOF_STATIC_LAMBDA_FUNCTION` use
0047 /// the `boost::hof::reveal` adaptor to improve error messages.
0048 /// 
0049 /// Note: due to compiler limitations, a global function declared with
0050 /// `BOOST_HOF_STATIC_LAMBDA_FUNCTION` is not guaranteed to have a unique 
0051 /// address across translation units when compiled with pre-C++17 MSVC.
0052 /// 
0053 /// Example
0054 /// -------
0055 /// 
0056 ///     #include <boost/hof.hpp>
0057 ///     #include <cassert>
0058 /// 
0059 ///     BOOST_HOF_STATIC_LAMBDA_FUNCTION(add_one) = [](int x)
0060 ///     {
0061 ///         return x + 1;
0062 ///     };
0063 ///     int main() {
0064 ///         assert(3 == add_one(2));
0065 ///     }
0066 /// 
0067 
0068 #include <boost/hof/config.hpp>
0069 
0070 // TODO: Move this to a detail header
0071 #if !BOOST_HOF_HAS_CONSTEXPR_LAMBDA || !BOOST_HOF_HAS_INLINE_LAMBDAS
0072 
0073 #include <type_traits>
0074 #include <utility>
0075 #include <boost/hof/detail/result_of.hpp>
0076 #include <boost/hof/reveal.hpp>
0077 #include <boost/hof/detail/constexpr_deduce.hpp>
0078 #include <boost/hof/function.hpp>
0079 
0080 
0081 #ifndef BOOST_HOF_REWRITE_STATIC_LAMBDA
0082 #ifdef _MSC_VER
0083 #define BOOST_HOF_REWRITE_STATIC_LAMBDA 1
0084 #else
0085 #define BOOST_HOF_REWRITE_STATIC_LAMBDA 0
0086 #endif
0087 #endif
0088 
0089 namespace boost { namespace hof {
0090 
0091 namespace detail {
0092 
0093 template<class F>
0094 struct static_function_wrapper
0095 {
0096     // Default constructor necessary for MSVC
0097     constexpr static_function_wrapper()
0098     {}
0099 
0100     static_assert(BOOST_HOF_IS_EMPTY(F), "Function or lambda expression must be empty");
0101 
0102     struct failure
0103     : failure_for<F>
0104     {};
0105 
0106     template<class... Ts>
0107     const F& base_function(Ts&&...) const
0108     {
0109         return reinterpret_cast<const F&>(*this);
0110     }
0111 
0112     BOOST_HOF_RETURNS_CLASS(static_function_wrapper);
0113 
0114     template<class... Ts>
0115     BOOST_HOF_SFINAE_RESULT(const F&, id_<Ts>...) 
0116     operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
0117     (
0118         BOOST_HOF_RETURNS_REINTERPRET_CAST(const F&)(*BOOST_HOF_CONST_THIS)(BOOST_HOF_FORWARD(Ts)(xs)...)
0119     );
0120 };
0121 
0122 struct static_function_wrapper_factor
0123 {
0124     constexpr static_function_wrapper_factor()
0125     {}
0126     template<class F>
0127     constexpr static_function_wrapper<F> operator= (const F&) const
0128     {
0129         // static_assert(std::is_literal_type<static_function_wrapper<F>>::value, "Function wrapper not a literal type");
0130         return {};
0131     }
0132 };
0133 
0134 #if BOOST_HOF_REWRITE_STATIC_LAMBDA
0135 template<class T, class=void>
0136 struct is_rewritable
0137 : std::false_type
0138 {};
0139 
0140 template<class T>
0141 struct is_rewritable<T, typename detail::holder<
0142     typename T::fit_rewritable_tag
0143 >::type>
0144 : std::is_same<typename T::fit_rewritable_tag, T>
0145 {};
0146 
0147 template<class T, class=void>
0148 struct is_rewritable1
0149 : std::false_type
0150 {};
0151 
0152 template<class T>
0153 struct is_rewritable1<T, typename detail::holder<
0154     typename T::fit_rewritable1_tag
0155 >::type>
0156 : std::is_same<typename T::fit_rewritable1_tag, T>
0157 {};
0158 
0159 
0160 template<class T, class=void>
0161 struct rewrite_lambda;
0162 
0163 template<template<class...> class Adaptor, class... Ts>
0164 struct rewrite_lambda<Adaptor<Ts...>, typename std::enable_if<
0165     is_rewritable<Adaptor<Ts...>>::value
0166 >::type>
0167 {
0168     typedef Adaptor<typename rewrite_lambda<Ts>::type...> type;
0169 };
0170 
0171 template<template<class...> class Adaptor, class T, class... Ts>
0172 struct rewrite_lambda<Adaptor<T, Ts...>, typename std::enable_if<
0173     is_rewritable1<Adaptor<T, Ts...>>::value
0174 >::type>
0175 {
0176     typedef Adaptor<typename rewrite_lambda<T>::type, Ts...> type;
0177 };
0178 
0179 template<class T>
0180 struct rewrite_lambda<T, typename std::enable_if<
0181     std::is_empty<T>::value && 
0182     !is_rewritable<T>::value && 
0183     !is_rewritable1<T>::value
0184 >::type>
0185 {
0186     typedef static_function_wrapper<T> type;
0187 };
0188 
0189 template<class T>
0190 struct rewrite_lambda<T, typename std::enable_if<
0191     !std::is_empty<T>::value && 
0192     !is_rewritable<T>::value && 
0193     !is_rewritable1<T>::value
0194 >::type>
0195 {
0196     typedef T type;
0197 };
0198 
0199 #endif
0200 
0201 template<class T>
0202 struct reveal_static_lambda_function_wrapper_factor
0203 {
0204     constexpr reveal_static_lambda_function_wrapper_factor()
0205     {}
0206 #if BOOST_HOF_REWRITE_STATIC_LAMBDA
0207     template<class F>
0208     constexpr reveal_adaptor<typename rewrite_lambda<F>::type> 
0209     operator=(const F&) const
0210     {
0211         return reveal_adaptor<typename rewrite_lambda<F>::type>();
0212     }
0213 #elif BOOST_HOF_HAS_CONST_FOLD
0214     template<class F>
0215     constexpr const reveal_adaptor<F>& operator=(const F&) const
0216     {
0217         return reinterpret_cast<const reveal_adaptor<F>&>(static_const_var<T>());
0218     }
0219 #else
0220     template<class F>
0221     constexpr reveal_adaptor<static_function_wrapper<F>> operator=(const F&) const
0222     {
0223         return {};
0224     }
0225 #endif
0226 };
0227 
0228 }}} // namespace boost::hof
0229 
0230 #endif
0231 
0232 #if BOOST_HOF_HAS_CONSTEXPR_LAMBDA
0233 #define BOOST_HOF_STATIC_LAMBDA []
0234 #else
0235 #define BOOST_HOF_DETAIL_MAKE_STATIC BOOST_HOF_DETAIL_CONSTEXPR_DEDUCE boost::hof::detail::static_function_wrapper_factor()
0236 #define BOOST_HOF_STATIC_LAMBDA BOOST_HOF_DETAIL_MAKE_STATIC = []
0237 #endif
0238 
0239 #if BOOST_HOF_HAS_INLINE_LAMBDAS
0240 #define BOOST_HOF_STATIC_LAMBDA_FUNCTION BOOST_HOF_STATIC_FUNCTION
0241 #else
0242 #define BOOST_HOF_DETAIL_MAKE_REVEAL_STATIC(T) BOOST_HOF_DETAIL_CONSTEXPR_DEDUCE_UNIQUE(T) boost::hof::detail::reveal_static_lambda_function_wrapper_factor<T>()
0243 #define BOOST_HOF_STATIC_LAMBDA_FUNCTION(name) \
0244 struct fit_private_static_function_ ## name {}; \
0245 BOOST_HOF_STATIC_AUTO_REF name = BOOST_HOF_DETAIL_MAKE_REVEAL_STATIC(fit_private_static_function_ ## name)
0246 #endif
0247 
0248 #endif