]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/type_erasure/free.hpp
update sources to ceph Nautilus 14.2.1
[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/preprocessor/control/if.hpp>
23 #include <boost/preprocessor/punctuation/is_begin_parens.hpp>
24 #include <boost/vmd/is_empty.hpp>
25 #include <boost/type_traits/remove_reference.hpp>
26 #include <boost/type_traits/remove_cv.hpp>
27 #include <boost/mpl/eval_if.hpp>
28 #include <boost/mpl/identity.hpp>
29 #include <boost/mpl/int.hpp>
30 #include <boost/mpl/next.hpp>
31 #include <boost/type_erasure/detail/macro.hpp>
32 #include <boost/type_erasure/detail/const.hpp>
33 #include <boost/type_erasure/config.hpp>
34 #include <boost/type_erasure/derived.hpp>
35 #include <boost/type_erasure/rebind_any.hpp>
36 #include <boost/type_erasure/param.hpp>
37 #include <boost/type_erasure/is_placeholder.hpp>
38 #include <boost/type_erasure/call.hpp>
39 #include <boost/type_erasure/concept_interface.hpp>
40
41 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || \
42 defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || \
43 defined(BOOST_TYPE_ERASURE_DOXYGEN) || \
44 BOOST_WORKAROUND(BOOST_MSVC, == 1800)
45
46 namespace boost {
47 namespace type_erasure {
48 namespace detail {
49
50 template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_TYPE_ERASURE_MAX_ARITY, class T, void)>
51 struct first_placeholder {
52 typedef typename ::boost::mpl::eval_if<is_placeholder<T0>,
53 ::boost::mpl::identity<T0>,
54 first_placeholder<BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_TYPE_ERASURE_MAX_ARITY, T)>
55 >::type type;
56 };
57
58 template<>
59 struct first_placeholder<> {};
60
61 template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_TYPE_ERASURE_MAX_ARITY, class T, void)>
62 struct first_placeholder_index :
63 ::boost::mpl::eval_if<is_placeholder<T0>,
64 ::boost::mpl::int_<0>,
65 ::boost::mpl::next<first_placeholder_index<BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_TYPE_ERASURE_MAX_ARITY, T)> >
66 >::type
67 {};
68
69 }
70 }
71 }
72
73 /** INTERNAL ONLY */
74 #define BOOST_TYPE_ERASURE_FREE_QUALIFIED_ID(seq, N) \
75 BOOST_TYPE_ERASURE_QUALIFIED_NAME(seq)<R(BOOST_PP_ENUM_PARAMS(N, T))>
76
77 /** INTERNAL ONLY */
78 #define BOOST_TYPE_ERASURE_FREE_UNQUALIFIED_PARAM_TYPE(z, n, data) \
79 typename ::boost::remove_cv<typename ::boost::remove_reference<BOOST_PP_CAT(T, n)>::type>::type
80
81 /** INTERNAL ONLY */
82 #define BOOST_TYPE_ERASURE_FREE_PARAM_TYPE(z, n, data) \
83 typename ::boost::mpl::eval_if_c<(_boost_type_erasure_free_p_idx::value == n), \
84 ::boost::type_erasure::detail::maybe_const_this_param<BOOST_PP_CAT(T, n), Base>, \
85 ::boost::type_erasure::as_param<Base, BOOST_PP_CAT(T, n)> \
86 >::type BOOST_PP_CAT(t, n)
87
88 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
89
90 /** INTERNAL ONLY */
91 #define BOOST_TYPE_ERASURE_FREE_FORWARD_I(z, n, data) ::std::forward<BOOST_PP_CAT(T, n)>(BOOST_PP_CAT(t, n))
92 /** INTERNAL ONLY */
93 #define BOOST_TYPE_ERASURE_FREE_FORWARD(n) BOOST_PP_ENUM(n, BOOST_TYPE_ERASURE_FREE_FORWARD_I, ~)
94 /** INTERNAL ONLY */
95 #define BOOST_TYPE_ERASURE_FREE_FORWARD_PARAM_I(z, n, data) \
96 ::std::forward<typename ::boost::mpl::eval_if_c<(_boost_type_erasure_free_p_idx::value == n), \
97 ::boost::type_erasure::detail::maybe_const_this_param<BOOST_PP_CAT(T, n), Base>, \
98 ::boost::type_erasure::as_param<Base, BOOST_PP_CAT(T, n)> \
99 >::type>(BOOST_PP_CAT(t, n))
100
101 #else
102
103 #define BOOST_TYPE_ERASURE_FREE_FORWARD(n) BOOST_PP_ENUM_PARAMS(n, t)
104 #define BOOST_TYPE_ERASURE_FREE_FORWARD_PARAM_I(z, n, data) BOOST_PP_CAT(t, n)
105
106 #endif
107
108 /** INTERNAL ONLY */
109 #define BOOST_TYPE_ERASURE_FREE_II(qual_name, concept_name, function_name, N) \
110 BOOST_TYPE_ERASURE_OPEN_NAMESPACE(qual_name) \
111 \
112 template<class Sig> \
113 struct concept_name; \
114 \
115 template<class R BOOST_PP_ENUM_TRAILING_PARAMS(N, class T)> \
116 struct concept_name<R(BOOST_PP_ENUM_PARAMS(N, T))> { \
117 static R apply(BOOST_PP_ENUM_BINARY_PARAMS(N, T, t)) \
118 { return function_name(BOOST_TYPE_ERASURE_FREE_FORWARD(N)); } \
119 }; \
120 \
121 template<BOOST_PP_ENUM_PARAMS(N, class T)> \
122 struct concept_name<void(BOOST_PP_ENUM_PARAMS(N, T))> { \
123 static void apply(BOOST_PP_ENUM_BINARY_PARAMS(N, T, t)) \
124 { function_name(BOOST_TYPE_ERASURE_FREE_FORWARD(N)); } \
125 }; \
126 \
127 BOOST_TYPE_ERASURE_CLOSE_NAMESPACE(qual_name) \
128 \
129 namespace boost { \
130 namespace type_erasure { \
131 \
132 template<class R BOOST_PP_ENUM_TRAILING_PARAMS(N, class T), class Base> \
133 struct concept_interface< \
134 BOOST_TYPE_ERASURE_FREE_QUALIFIED_ID(qual_name, N), \
135 Base, \
136 typename ::boost::type_erasure::detail::first_placeholder< \
137 BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_FREE_UNQUALIFIED_PARAM_TYPE, ~)>::type \
138 > : Base { \
139 typedef typename ::boost::type_erasure::detail::first_placeholder_index< \
140 BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_FREE_UNQUALIFIED_PARAM_TYPE, ~)>::type \
141 _boost_type_erasure_free_p_idx; \
142 friend typename ::boost::type_erasure::rebind_any<Base, R>::type function_name( \
143 BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_FREE_PARAM_TYPE, ~)) \
144 { \
145 return ::boost::type_erasure::call( \
146 BOOST_TYPE_ERASURE_FREE_QUALIFIED_ID(qual_name, N)() \
147 BOOST_PP_ENUM_TRAILING(N, BOOST_TYPE_ERASURE_FREE_FORWARD_PARAM_I, ~)); \
148 } \
149 }; \
150 \
151 } \
152 }
153
154 /** INTERNAL ONLY */
155 #define BOOST_TYPE_ERASURE_FREE_I(namespace_name, concept_name, function_name, N)\
156 BOOST_TYPE_ERASURE_FREE_II(namespace_name, concept_name, function_name, N)
157
158 #ifdef BOOST_TYPE_ERASURE_DOXYGEN
159
160 /**
161 * \brief Defines a primitive concept for a free function.
162 *
163 * \param concept_name is the name of the concept to declare.
164 * If it is omitted it defaults to <code>has_ ## function_name</code>
165 * \param function_name is the name of the function.
166 *
167 * The declaration of the concept is
168 * \code
169 * template<class Sig>
170 * struct concept_name;
171 * \endcode
172 * where Sig is a function type giving the
173 * signature of the function.
174 *
175 * This macro can only be used at namespace scope.
176 *
177 * Example:
178 *
179 * \code
180 * BOOST_TYPE_ERASURE_FREE(to_string)
181 * typedef has_to_string<std::string(_self const&)> to_string_concept;
182 * \endcode
183 *
184 * In C++03, the macro can only be used in the global namespace and
185 * is defined as:
186 *
187 * \code
188 * #define BOOST_TYPE_ERASURE_FREE(qualified_name, function_name, N)
189 * \endcode
190 *
191 * Example:
192 *
193 * \code
194 * BOOST_TYPE_ERASURE_FREE((boost)(has_to_string), to_string, 1)
195 * \endcode
196 *
197 * For backwards compatibility, this form is always accepted.
198 */
199 #define BOOST_TYPE_ERASURE_FREE(concept_name, function_name)
200
201 #else
202
203 #define BOOST_TYPE_ERASURE_FREE(qualified_name, function_name, N) \
204 BOOST_TYPE_ERASURE_FREE_I( \
205 qualified_name, \
206 BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(qualified_name)), qualified_name), \
207 function_name, \
208 N)
209
210 #endif
211
212 #else
213
214 namespace boost {
215 namespace type_erasure {
216
217 template<int... N>
218 struct index_list {};
219
220 namespace detail {
221
222 template<class... T>
223 struct first_placeholder;
224
225 template<class T0, class... T>
226 struct first_placeholder<T0, T...> {
227 typedef typename ::boost::mpl::eval_if<is_placeholder<T0>,
228 ::boost::mpl::identity<T0>,
229 first_placeholder<T...>
230 >::type type;
231 };
232
233 template<>
234 struct first_placeholder<> {};
235
236 template<class... T>
237 struct first_placeholder_index;
238
239 template<class T0, class... T>
240 struct first_placeholder_index<T0, T...> :
241 ::boost::mpl::eval_if<is_placeholder<T0>,
242 ::boost::mpl::int_<0>,
243 ::boost::mpl::next<first_placeholder_index<T...> >
244 >::type
245 {};
246
247 template<class Sig>
248 struct transform_free_signature;
249
250 template<class T, int N>
251 struct push_back_index;
252
253 template<int... N, int X>
254 struct push_back_index<index_list<N...>, X>
255 {
256 typedef index_list<N..., X> type;
257 };
258
259 template<int N>
260 struct make_index_list {
261 typedef typename push_back_index<
262 typename make_index_list<N-1>::type,
263 N-1
264 >::type type;
265 };
266
267 template<>
268 struct make_index_list<0> {
269 typedef index_list<> type;
270 };
271
272 #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && \
273 !defined(BOOST_NO_CXX11_DECLTYPE)
274
275 template<int N>
276 using make_index_list_t = typename ::boost::type_erasure::detail::make_index_list<N>::type;
277
278 #if BOOST_WORKAROUND(BOOST_MSVC, == 1900)
279
280 template<class... T>
281 struct first_placeholder_index_ :
282 ::boost::type_erasure::detail::first_placeholder_index<
283 ::boost::remove_cv_t< ::boost::remove_reference_t<T> >...
284 >
285 {};
286 template<class... T>
287 using first_placeholder_index_t =
288 typename ::boost::type_erasure::detail::first_placeholder_index_<T...>::type;
289
290 #else
291
292 template<class... T>
293 using first_placeholder_index_t =
294 typename ::boost::type_erasure::detail::first_placeholder_index<
295 ::boost::remove_cv_t< ::boost::remove_reference_t<T> >...
296 >::type;
297
298 #endif
299
300 template<class Base, class Tn, int I, class... T>
301 using free_param_t =
302 typename ::boost::mpl::eval_if_c<(::boost::type_erasure::detail::first_placeholder_index_t<T...>::value == I),
303 ::boost::type_erasure::detail::maybe_const_this_param<Tn, Base>, \
304 ::boost::type_erasure::as_param<Base, Tn>
305 >::type;
306
307 template<class Sig, class ID>
308 struct free_interface_chooser
309 {
310 template<class Base, template<class> class C, template<class...> class F>
311 using apply = Base;
312 };
313
314 template<class R, class... A>
315 struct free_interface_chooser<
316 R(A...),
317 typename ::boost::type_erasure::detail::first_placeholder<
318 ::boost::remove_cv_t< ::boost::remove_reference_t<A> >...>::type>
319 {
320 template<class Base, template<class> class C, template<class...> class F>
321 using apply = F<R(A...), Base,
322 ::boost::type_erasure::detail::make_index_list_t<sizeof...(A)> >;
323 };
324
325 template<class Sig, template<class> class C, template<class...> class F>
326 struct free_choose_interface {
327 template<class Concept, class Base, class ID>
328 using apply = typename free_interface_chooser<Sig, ID>::template apply<Base, C, F>;
329 };
330
331 /** INTERNAL ONLY */
332 #define BOOST_TYPE_ERASURE_FREE_I(concept_name, function_name) \
333 template<class Sig> \
334 struct concept_name; \
335 \
336 namespace boost_type_erasure_impl { \
337 \
338 template<class Sig, class Base, class Idx> \
339 struct concept_name ## _free_interface; \
340 template<class R, class... T, class Base, int... I> \
341 struct concept_name ## _free_interface<R(T...), Base, ::boost::type_erasure::index_list<I...> > : Base {\
342 friend ::boost::type_erasure::rebind_any_t<Base, R> \
343 function_name( \
344 ::boost::type_erasure::detail::free_param_t<Base, T, I, T...>... t) \
345 { \
346 return ::boost::type_erasure::call( \
347 concept_name<R(T...)>(), \
348 std::forward< ::boost::type_erasure::detail::free_param_t<Base, T, I, T...> >(t)...);\
349 } \
350 }; \
351 \
352 template<class Sig> \
353 struct concept_name ## free; \
354 \
355 template<class R, class... T> \
356 struct concept_name ## free<R(T...)> { \
357 static R apply(T... t) \
358 { return function_name(std::forward<T>(t)...); } \
359 }; \
360 \
361 template<class... T> \
362 struct concept_name ## free<void(T...)> { \
363 static void apply(T... t) \
364 { function_name(std::forward<T>(t)...); } \
365 }; \
366 \
367 } \
368 \
369 template<class Sig> \
370 struct concept_name : \
371 boost_type_erasure_impl::concept_name##free<Sig> \
372 {}; \
373 \
374 template<class Sig> \
375 ::boost::type_erasure::detail::free_choose_interface<Sig, concept_name, \
376 boost_type_erasure_impl::concept_name ## _free_interface> \
377 boost_type_erasure_find_interface(concept_name<Sig>);
378
379 #define BOOST_TYPE_ERASURE_FREE_SIMPLE(name, ...) \
380 BOOST_TYPE_ERASURE_FREE_I(has_ ## name, name)
381
382 #define BOOST_TYPE_ERASURE_FREE_NS_I(concept_name, name) \
383 BOOST_TYPE_ERASURE_FREE_I(concept_name, name)
384
385 #define BOOST_TYPE_ERASURE_FREE_NS(concept_name, name) \
386 BOOST_TYPE_ERASURE_OPEN_NAMESPACE(concept_name) \
387 BOOST_TYPE_ERASURE_FREE_NS_I(BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(concept_name)), concept_name), name) \
388 BOOST_TYPE_ERASURE_CLOSE_NAMESPACE(concept_name)
389
390 #define BOOST_TYPE_ERASURE_FREE_NAMED(concept_name, name, ...) \
391 BOOST_PP_IF(BOOST_PP_IS_BEGIN_PARENS(concept_name), \
392 BOOST_TYPE_ERASURE_FREE_NS, \
393 BOOST_TYPE_ERASURE_FREE_I) \
394 (concept_name, name)
395
396 #define BOOST_TYPE_ERASURE_FREE_CAT(x, y) x y
397
398 #define BOOST_TYPE_ERASURE_FREE(name, ...) \
399 BOOST_TYPE_ERASURE_FREE_CAT( \
400 BOOST_PP_IF(BOOST_VMD_IS_EMPTY(__VA_ARGS__), \
401 BOOST_TYPE_ERASURE_FREE_SIMPLE, \
402 BOOST_TYPE_ERASURE_FREE_NAMED), \
403 (name, __VA_ARGS__))
404
405 #else
406
407 /** INTERNAL ONLY */
408 #define BOOST_TYPE_ERASURE_FREE_II(qual_name, concept_name, function_name) \
409 BOOST_TYPE_ERASURE_OPEN_NAMESPACE(qual_name) \
410 \
411 template<class Sig> \
412 struct concept_name; \
413 \
414 template<class R, class... T> \
415 struct concept_name<R(T...)> { \
416 static R apply(T... t) \
417 { return function_name(std::forward<T>(t)...); } \
418 }; \
419 \
420 template<class... T> \
421 struct concept_name<void(T...)> { \
422 static void apply(T... t) \
423 { function_name(std::forward<T>(t)...); } \
424 }; \
425 \
426 BOOST_TYPE_ERASURE_CLOSE_NAMESPACE(qual_name) \
427 \
428 namespace boost { \
429 namespace type_erasure { \
430 \
431 template<class Sig, class Base, class Idx> \
432 struct inject ## concept_name; \
433 template<class R, class... T, class Base, int... I> \
434 struct inject ## concept_name<R(T...), Base, index_list<I...> > : Base {\
435 typedef typename ::boost::type_erasure::detail::first_placeholder_index< \
436 typename ::boost::remove_cv< \
437 typename ::boost::remove_reference<T>::type \
438 >::type... \
439 >::type _boost_type_erasure_free_p_idx; \
440 friend typename ::boost::type_erasure::rebind_any<Base, R>::type\
441 function_name( \
442 typename ::boost::mpl::eval_if_c<(_boost_type_erasure_free_p_idx::value == I), \
443 ::boost::type_erasure::detail::maybe_const_this_param<T, Base>, \
444 ::boost::type_erasure::as_param<Base, T> \
445 >::type... t) \
446 { \
447 return ::boost::type_erasure::call( \
448 BOOST_TYPE_ERASURE_QUALIFIED_NAME(qual_name)<R(T...)>(),\
449 std::forward<typename ::boost::mpl::eval_if_c<(_boost_type_erasure_free_p_idx::value == I), \
450 ::boost::type_erasure::detail::maybe_const_this_param<T, Base>, \
451 ::boost::type_erasure::as_param<Base, T> \
452 >::type>(t)...); \
453 } \
454 }; \
455 \
456 template<class R, class... T, class Base> \
457 struct concept_interface< \
458 BOOST_TYPE_ERASURE_QUALIFIED_NAME(qual_name)<R(T...)>, \
459 Base, \
460 typename ::boost::type_erasure::detail::first_placeholder< \
461 typename ::boost::remove_cv<typename ::boost::remove_reference<T>::type>::type...>::type \
462 > : inject ## concept_name<R(T...), Base, typename ::boost::type_erasure::detail::make_index_list<sizeof...(T)>::type>\
463 {}; \
464 \
465 } \
466 }
467
468
469 /** INTERNAL ONLY */
470 #define BOOST_TYPE_ERASURE_FREE_I(namespace_name, concept_name, function_name) \
471 BOOST_TYPE_ERASURE_FREE_II(namespace_name, concept_name, function_name)
472
473 #define BOOST_TYPE_ERASURE_FREE(qualified_name, function_name, ...) \
474 BOOST_TYPE_ERASURE_FREE_I( \
475 qualified_name, \
476 BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(qualified_name)), qualified_name), \
477 function_name)
478
479 #endif
480
481 }
482 }
483 }
484
485 #endif
486
487 #endif