]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/hof/lambda.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / hof / lambda.hpp
1 /*=============================================================================
2 Copyright (c) 2014 Paul Fultz II
3 lambda.h
4 Distributed under the Boost Software License, Version 1.0. (See accompanying
5 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 ==============================================================================*/
7
8 #ifndef BOOST_HOF_GUARD_FUNCTION_LAMBDA_H
9 #define BOOST_HOF_GUARD_FUNCTION_LAMBDA_H
10
11 /// BOOST_HOF_STATIC_LAMBDA
12 /// =================
13 ///
14 /// Description
15 /// -----------
16 ///
17 /// The `BOOST_HOF_STATIC_LAMBDA` macro allows initializing non-capturing lambdas at
18 /// compile-time in a `constexpr` expression.
19 ///
20 /// Example
21 /// -------
22 ///
23 /// #include <boost/hof.hpp>
24 /// #include <cassert>
25 ///
26 /// const constexpr auto add_one = BOOST_HOF_STATIC_LAMBDA(int x)
27 /// {
28 /// return x + 1;
29 /// };
30 ///
31 /// int main() {
32 /// assert(3 == add_one(2));
33 /// }
34 ///
35 /// BOOST_HOF_STATIC_LAMBDA_FUNCTION
36 /// ==========================
37 ///
38 /// Description
39 /// -----------
40 ///
41 /// The `BOOST_HOF_STATIC_LAMBDA_FUNCTION` macro allows initializing a global
42 /// function object that contains non-capturing lambdas. It also ensures that
43 /// the global function object has a unique address across translation units.
44 /// This helps prevent possible ODR-violations.
45 ///
46 /// By default, all functions defined with `BOOST_HOF_STATIC_LAMBDA_FUNCTION` use
47 /// the `boost::hof::reveal` adaptor to improve error messages.
48 ///
49 /// Note: due to compiler limitations, a global function declared with
50 /// `BOOST_HOF_STATIC_LAMBDA_FUNCTION` is not guaranteed to have a unique
51 /// address across translation units when compiled with pre-C++17 MSVC.
52 ///
53 /// Example
54 /// -------
55 ///
56 /// #include <boost/hof.hpp>
57 /// #include <cassert>
58 ///
59 /// BOOST_HOF_STATIC_LAMBDA_FUNCTION(add_one) = [](int x)
60 /// {
61 /// return x + 1;
62 /// };
63 /// int main() {
64 /// assert(3 == add_one(2));
65 /// }
66 ///
67
68 #include <boost/hof/config.hpp>
69
70 // TODO: Move this to a detail header
71 #if !BOOST_HOF_HAS_CONSTEXPR_LAMBDA || !BOOST_HOF_HAS_INLINE_LAMBDAS
72
73 #include <type_traits>
74 #include <utility>
75 #include <boost/hof/detail/result_of.hpp>
76 #include <boost/hof/reveal.hpp>
77 #include <boost/hof/detail/constexpr_deduce.hpp>
78 #include <boost/hof/function.hpp>
79
80
81 #ifndef BOOST_HOF_REWRITE_STATIC_LAMBDA
82 #ifdef _MSC_VER
83 #define BOOST_HOF_REWRITE_STATIC_LAMBDA 1
84 #else
85 #define BOOST_HOF_REWRITE_STATIC_LAMBDA 0
86 #endif
87 #endif
88
89 namespace boost { namespace hof {
90
91 namespace detail {
92
93 template<class F>
94 struct static_function_wrapper
95 {
96 // Default constructor necessary for MSVC
97 constexpr static_function_wrapper()
98 {}
99
100 static_assert(BOOST_HOF_IS_EMPTY(F), "Function or lambda expression must be empty");
101
102 struct failure
103 : failure_for<F>
104 {};
105
106 template<class... Ts>
107 const F& base_function(Ts&&...) const
108 {
109 return reinterpret_cast<const F&>(*this);
110 }
111
112 BOOST_HOF_RETURNS_CLASS(static_function_wrapper);
113
114 template<class... Ts>
115 BOOST_HOF_SFINAE_RESULT(const F&, id_<Ts>...)
116 operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
117 (
118 BOOST_HOF_RETURNS_REINTERPRET_CAST(const F&)(*BOOST_HOF_CONST_THIS)(BOOST_HOF_FORWARD(Ts)(xs)...)
119 );
120 };
121
122 struct static_function_wrapper_factor
123 {
124 constexpr static_function_wrapper_factor()
125 {}
126 template<class F>
127 constexpr static_function_wrapper<F> operator= (const F&) const
128 {
129 // static_assert(std::is_literal_type<static_function_wrapper<F>>::value, "Function wrapper not a literal type");
130 return {};
131 }
132 };
133
134 #if BOOST_HOF_REWRITE_STATIC_LAMBDA
135 template<class T, class=void>
136 struct is_rewritable
137 : std::false_type
138 {};
139
140 template<class T>
141 struct is_rewritable<T, typename detail::holder<
142 typename T::fit_rewritable_tag
143 >::type>
144 : std::is_same<typename T::fit_rewritable_tag, T>
145 {};
146
147 template<class T, class=void>
148 struct is_rewritable1
149 : std::false_type
150 {};
151
152 template<class T>
153 struct is_rewritable1<T, typename detail::holder<
154 typename T::fit_rewritable1_tag
155 >::type>
156 : std::is_same<typename T::fit_rewritable1_tag, T>
157 {};
158
159
160 template<class T, class=void>
161 struct rewrite_lambda;
162
163 template<template<class...> class Adaptor, class... Ts>
164 struct rewrite_lambda<Adaptor<Ts...>, typename std::enable_if<
165 is_rewritable<Adaptor<Ts...>>::value
166 >::type>
167 {
168 typedef Adaptor<typename rewrite_lambda<Ts>::type...> type;
169 };
170
171 template<template<class...> class Adaptor, class T, class... Ts>
172 struct rewrite_lambda<Adaptor<T, Ts...>, typename std::enable_if<
173 is_rewritable1<Adaptor<T, Ts...>>::value
174 >::type>
175 {
176 typedef Adaptor<typename rewrite_lambda<T>::type, Ts...> type;
177 };
178
179 template<class T>
180 struct rewrite_lambda<T, typename std::enable_if<
181 std::is_empty<T>::value &&
182 !is_rewritable<T>::value &&
183 !is_rewritable1<T>::value
184 >::type>
185 {
186 typedef static_function_wrapper<T> type;
187 };
188
189 template<class T>
190 struct rewrite_lambda<T, typename std::enable_if<
191 !std::is_empty<T>::value &&
192 !is_rewritable<T>::value &&
193 !is_rewritable1<T>::value
194 >::type>
195 {
196 typedef T type;
197 };
198
199 #endif
200
201 template<class T>
202 struct reveal_static_lambda_function_wrapper_factor
203 {
204 constexpr reveal_static_lambda_function_wrapper_factor()
205 {}
206 #if BOOST_HOF_REWRITE_STATIC_LAMBDA
207 template<class F>
208 constexpr reveal_adaptor<typename rewrite_lambda<F>::type>
209 operator=(const F&) const
210 {
211 return reveal_adaptor<typename rewrite_lambda<F>::type>();
212 }
213 #elif BOOST_HOF_HAS_CONST_FOLD
214 template<class F>
215 constexpr const reveal_adaptor<F>& operator=(const F&) const
216 {
217 return reinterpret_cast<const reveal_adaptor<F>&>(static_const_var<T>());
218 }
219 #else
220 template<class F>
221 constexpr reveal_adaptor<static_function_wrapper<F>> operator=(const F&) const
222 {
223 return {};
224 }
225 #endif
226 };
227
228 }}} // namespace boost::hof
229
230 #endif
231
232 #if BOOST_HOF_HAS_CONSTEXPR_LAMBDA
233 #define BOOST_HOF_STATIC_LAMBDA []
234 #else
235 #define BOOST_HOF_DETAIL_MAKE_STATIC BOOST_HOF_DETAIL_CONSTEXPR_DEDUCE boost::hof::detail::static_function_wrapper_factor()
236 #define BOOST_HOF_STATIC_LAMBDA BOOST_HOF_DETAIL_MAKE_STATIC = []
237 #endif
238
239 #if BOOST_HOF_HAS_INLINE_LAMBDAS
240 #define BOOST_HOF_STATIC_LAMBDA_FUNCTION BOOST_HOF_STATIC_FUNCTION
241 #else
242 #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>()
243 #define BOOST_HOF_STATIC_LAMBDA_FUNCTION(name) \
244 struct fit_private_static_function_ ## name {}; \
245 BOOST_HOF_STATIC_AUTO_REF name = BOOST_HOF_DETAIL_MAKE_REVEAL_STATIC(fit_private_static_function_ ## name)
246 #endif
247
248 #endif