]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/type_erasure/free.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / type_erasure / free.hpp
1 // Boost.TypeErasure library
2 //
3 // Copyright 2012 Steven Watanabe
4 //
5 // Distributed under the Boost Software License Version 1.0. (See
6 // accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
8 //
9 // $Id$
10
11 #ifndef BOOST_TYPE_ERASURE_FREE_HPP_INCLUDED
12 #define BOOST_TYPE_ERASURE_FREE_HPP_INCLUDED
13
14 #include <boost/detail/workaround.hpp>
15 #include <boost/preprocessor/repetition/enum.hpp>
16 #include <boost/preprocessor/repetition/enum_trailing.hpp>
17 #include <boost/preprocessor/repetition/enum_params.hpp>
18 #include <boost/preprocessor/repetition/enum_shifted_params.hpp>
19 #include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
20 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
21 #include <boost/preprocessor/cat.hpp>
22 #include <boost/type_traits/remove_reference.hpp>
23 #include <boost/type_traits/remove_cv.hpp>
24 #include <boost/mpl/eval_if.hpp>
25 #include <boost/mpl/identity.hpp>
26 #include <boost/mpl/int.hpp>
27 #include <boost/mpl/next.hpp>
28 #include <boost/type_erasure/detail/macro.hpp>
29 #include <boost/type_erasure/detail/const.hpp>
30 #include <boost/type_erasure/config.hpp>
31 #include <boost/type_erasure/derived.hpp>
32 #include <boost/type_erasure/rebind_any.hpp>
33 #include <boost/type_erasure/param.hpp>
34 #include <boost/type_erasure/is_placeholder.hpp>
35 #include <boost/type_erasure/call.hpp>
36 #include <boost/type_erasure/concept_interface.hpp>
37
38 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || \
39 defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || \
40 defined(BOOST_TYPE_ERASURE_DOXYGEN) || \
41 BOOST_WORKAROUND(BOOST_MSVC, == 1800)
42
43 namespace boost {
44 namespace type_erasure {
45 namespace detail {
46
47 template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_TYPE_ERASURE_MAX_ARITY, class T, void)>
48 struct first_placeholder {
49 typedef typename ::boost::mpl::eval_if<is_placeholder<T0>,
50 ::boost::mpl::identity<T0>,
51 first_placeholder<BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_TYPE_ERASURE_MAX_ARITY, T)>
52 >::type type;
53 };
54
55 template<>
56 struct first_placeholder<> {};
57
58 template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_TYPE_ERASURE_MAX_ARITY, class T, void)>
59 struct first_placeholder_index :
60 ::boost::mpl::eval_if<is_placeholder<T0>,
61 ::boost::mpl::int_<0>,
62 ::boost::mpl::next<first_placeholder_index<BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_TYPE_ERASURE_MAX_ARITY, T)> >
63 >::type
64 {};
65
66 }
67 }
68 }
69
70 /** INTERNAL ONLY */
71 #define BOOST_TYPE_ERASURE_FREE_QUALIFIED_ID(seq, N) \
72 BOOST_TYPE_ERASURE_QUALIFIED_NAME(seq)<R(BOOST_PP_ENUM_PARAMS(N, T))>
73
74 /** INTERNAL ONLY */
75 #define BOOST_TYPE_ERASURE_FREE_UNQUALIFIED_PARAM_TYPE(z, n, data) \
76 typename ::boost::remove_cv<typename ::boost::remove_reference<BOOST_PP_CAT(T, n)>::type>::type
77
78 /** INTERNAL ONLY */
79 #define BOOST_TYPE_ERASURE_FREE_PARAM_TYPE(z, n, data) \
80 typename ::boost::mpl::eval_if_c<(_boost_type_erasure_free_p_idx::value == n), \
81 ::boost::type_erasure::detail::maybe_const_this_param<BOOST_PP_CAT(T, n), Base>, \
82 ::boost::type_erasure::as_param<Base, BOOST_PP_CAT(T, n)> \
83 >::type BOOST_PP_CAT(t, n)
84
85 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
86
87 /** INTERNAL ONLY */
88 #define BOOST_TYPE_ERASURE_FREE_FORWARD_I(z, n, data) ::std::forward<BOOST_PP_CAT(T, n)>(BOOST_PP_CAT(t, n))
89 /** INTERNAL ONLY */
90 #define BOOST_TYPE_ERASURE_FREE_FORWARD(n) BOOST_PP_ENUM(n, BOOST_TYPE_ERASURE_FREE_FORWARD_I, ~)
91 /** INTERNAL ONLY */
92 #define BOOST_TYPE_ERASURE_FREE_FORWARD_PARAM_I(z, n, data) \
93 ::std::forward<typename ::boost::mpl::eval_if_c<(_boost_type_erasure_free_p_idx::value == n), \
94 ::boost::type_erasure::detail::maybe_const_this_param<BOOST_PP_CAT(T, n), Base>, \
95 ::boost::type_erasure::as_param<Base, BOOST_PP_CAT(T, n)> \
96 >::type>(BOOST_PP_CAT(t, n))
97
98 #else
99
100 #define BOOST_TYPE_ERASURE_FREE_FORWARD(n) BOOST_PP_ENUM_PARAMS(n, t)
101 #define BOOST_TYPE_ERASURE_FREE_FORWARD_PARAM_I(z, n, data) BOOST_PP_CAT(t, n)
102
103 #endif
104
105 /** INTERNAL ONLY */
106 #define BOOST_TYPE_ERASURE_FREE_II(qual_name, concept_name, function_name, N) \
107 BOOST_TYPE_ERASURE_OPEN_NAMESPACE(qual_name) \
108 \
109 template<class Sig> \
110 struct concept_name; \
111 \
112 template<class R BOOST_PP_ENUM_TRAILING_PARAMS(N, class T)> \
113 struct concept_name<R(BOOST_PP_ENUM_PARAMS(N, T))> { \
114 static R apply(BOOST_PP_ENUM_BINARY_PARAMS(N, T, t)) \
115 { return function_name(BOOST_TYPE_ERASURE_FREE_FORWARD(N)); } \
116 }; \
117 \
118 template<BOOST_PP_ENUM_PARAMS(N, class T)> \
119 struct concept_name<void(BOOST_PP_ENUM_PARAMS(N, T))> { \
120 static void apply(BOOST_PP_ENUM_BINARY_PARAMS(N, T, t)) \
121 { function_name(BOOST_TYPE_ERASURE_FREE_FORWARD(N)); } \
122 }; \
123 \
124 BOOST_TYPE_ERASURE_CLOSE_NAMESPACE(qual_name) \
125 \
126 namespace boost { \
127 namespace type_erasure { \
128 \
129 template<class R BOOST_PP_ENUM_TRAILING_PARAMS(N, class T), class Base> \
130 struct concept_interface< \
131 BOOST_TYPE_ERASURE_FREE_QUALIFIED_ID(qual_name, N), \
132 Base, \
133 typename ::boost::type_erasure::detail::first_placeholder< \
134 BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_FREE_UNQUALIFIED_PARAM_TYPE, ~)>::type \
135 > : Base { \
136 typedef typename ::boost::type_erasure::detail::first_placeholder_index< \
137 BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_FREE_UNQUALIFIED_PARAM_TYPE, ~)>::type \
138 _boost_type_erasure_free_p_idx; \
139 friend typename ::boost::type_erasure::rebind_any<Base, R>::type function_name( \
140 BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_FREE_PARAM_TYPE, ~)) \
141 { \
142 return ::boost::type_erasure::call( \
143 BOOST_TYPE_ERASURE_FREE_QUALIFIED_ID(qual_name, N)() \
144 BOOST_PP_ENUM_TRAILING(N, BOOST_TYPE_ERASURE_FREE_FORWARD_PARAM_I, ~)); \
145 } \
146 }; \
147 \
148 } \
149 }
150
151 #else
152
153 namespace boost {
154 namespace type_erasure {
155
156 template<int... N>
157 struct index_list {};
158
159 namespace detail {
160
161 template<class... T>
162 struct first_placeholder;
163
164 template<class T0, class... T>
165 struct first_placeholder<T0, T...> {
166 typedef typename ::boost::mpl::eval_if<is_placeholder<T0>,
167 ::boost::mpl::identity<T0>,
168 first_placeholder<T...>
169 >::type type;
170 };
171
172 template<>
173 struct first_placeholder<> {};
174
175 template<class... T>
176 struct first_placeholder_index;
177
178 template<class T0, class... T>
179 struct first_placeholder_index<T0, T...> :
180 ::boost::mpl::eval_if<is_placeholder<T0>,
181 ::boost::mpl::int_<0>,
182 ::boost::mpl::next<first_placeholder_index<T...> >
183 >::type
184 {};
185
186 template<class Sig>
187 struct transform_free_signature;
188
189 template<class T, int N>
190 struct push_back_index;
191
192 template<int... N, int X>
193 struct push_back_index<index_list<N...>, X>
194 {
195 typedef index_list<N..., X> type;
196 };
197
198 template<int N>
199 struct make_index_list {
200 typedef typename push_back_index<
201 typename make_index_list<N-1>::type,
202 N-1
203 >::type type;
204 };
205
206 template<>
207 struct make_index_list<0> {
208 typedef index_list<> type;
209 };
210
211 }
212 }
213 }
214
215 /** INTERNAL ONLY */
216 #define BOOST_TYPE_ERASURE_FREE_II(qual_name, concept_name, function_name, N) \
217 BOOST_TYPE_ERASURE_OPEN_NAMESPACE(qual_name) \
218 \
219 template<class Sig> \
220 struct concept_name; \
221 \
222 template<class R, class... T> \
223 struct concept_name<R(T...)> { \
224 static R apply(T... t) \
225 { return function_name(std::forward<T>(t)...); } \
226 }; \
227 \
228 template<class... T> \
229 struct concept_name<void(T...)> { \
230 static void apply(T... t) \
231 { function_name(std::forward<T>(t)...); } \
232 }; \
233 \
234 BOOST_TYPE_ERASURE_CLOSE_NAMESPACE(qual_name) \
235 \
236 namespace boost { \
237 namespace type_erasure { \
238 \
239 template<class Sig, class Base, class Idx> \
240 struct inject ## concept_name; \
241 template<class R, class... T, class Base, int... I> \
242 struct inject ## concept_name<R(T...), Base, index_list<I...> > : Base {\
243 typedef typename ::boost::type_erasure::detail::first_placeholder_index< \
244 typename ::boost::remove_cv< \
245 typename ::boost::remove_reference<T>::type \
246 >::type... \
247 >::type _boost_type_erasure_free_p_idx; \
248 friend typename ::boost::type_erasure::rebind_any<Base, R>::type\
249 function_name( \
250 typename ::boost::mpl::eval_if_c<(_boost_type_erasure_free_p_idx::value == I), \
251 ::boost::type_erasure::detail::maybe_const_this_param<T, Base>, \
252 ::boost::type_erasure::as_param<Base, T> \
253 >::type... t) \
254 { \
255 return ::boost::type_erasure::call( \
256 BOOST_TYPE_ERASURE_QUALIFIED_NAME(qual_name)<R(T...)>(),\
257 std::forward<typename ::boost::mpl::eval_if_c<(_boost_type_erasure_free_p_idx::value == I), \
258 ::boost::type_erasure::detail::maybe_const_this_param<T, Base>, \
259 ::boost::type_erasure::as_param<Base, T> \
260 >::type>(t)...); \
261 } \
262 }; \
263 \
264 template<class R, class... T, class Base> \
265 struct concept_interface< \
266 BOOST_TYPE_ERASURE_QUALIFIED_NAME(qual_name)<R(T...)>, \
267 Base, \
268 typename ::boost::type_erasure::detail::first_placeholder< \
269 typename ::boost::remove_cv<typename ::boost::remove_reference<T>::type>::type...>::type \
270 > : inject ## concept_name<R(T...), Base, typename ::boost::type_erasure::detail::make_index_list<sizeof...(T)>::type>\
271 {}; \
272 \
273 } \
274 }
275
276 #endif
277
278 /** INTERNAL ONLY */
279 #define BOOST_TYPE_ERASURE_FREE_I(namespace_name, concept_name, function_name, N)\
280 BOOST_TYPE_ERASURE_FREE_II(namespace_name, concept_name, function_name, N)
281
282 /**
283 * \brief Defines a primitive concept for a free function.
284 *
285 * \param qualified_name should be a preprocessor sequence
286 * of the form (namespace1)(namespace2)...(concept_name).
287 * \param function_name is the name of the function.
288 * \param N is the number of arguments of the function.
289 *
290 * The declaration of the concept is
291 * \code
292 * template<class Sig>
293 * struct ::namespace1::namespace2::...::concept_name;
294 * \endcode
295 * where Sig is a function type giving the
296 * signature of the function.
297 *
298 * This macro can only be used in the global namespace.
299 *
300 * Example:
301 *
302 * \code
303 * BOOST_TYPE_ERASURE_FREE((boost)(has_to_string), to_string, 1)
304 * \endcode
305 */
306 #define BOOST_TYPE_ERASURE_FREE(qualified_name, function_name, N) \
307 BOOST_TYPE_ERASURE_FREE_I( \
308 qualified_name, \
309 BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(qualified_name)), qualified_name), \
310 function_name, \
311 N)
312
313 #endif