File indexing completed on 2025-12-16 10:10:13
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_TYPE_ERASURE_FREE_HPP_INCLUDED
0012 #define BOOST_TYPE_ERASURE_FREE_HPP_INCLUDED
0013
0014 #include <boost/detail/workaround.hpp>
0015 #include <boost/preprocessor/repetition/enum.hpp>
0016 #include <boost/preprocessor/repetition/enum_trailing.hpp>
0017 #include <boost/preprocessor/repetition/enum_params.hpp>
0018 #include <boost/preprocessor/repetition/enum_shifted_params.hpp>
0019 #include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
0020 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
0021 #include <boost/preprocessor/cat.hpp>
0022 #include <boost/preprocessor/control/if.hpp>
0023 #include <boost/preprocessor/punctuation/is_begin_parens.hpp>
0024 #include <boost/vmd/is_empty.hpp>
0025 #include <boost/type_traits/remove_reference.hpp>
0026 #include <boost/type_traits/remove_cv.hpp>
0027 #include <boost/mpl/eval_if.hpp>
0028 #include <boost/mpl/identity.hpp>
0029 #include <boost/mpl/int.hpp>
0030 #include <boost/mpl/next.hpp>
0031 #include <boost/type_erasure/detail/macro.hpp>
0032 #include <boost/type_erasure/detail/const.hpp>
0033 #include <boost/type_erasure/config.hpp>
0034 #include <boost/type_erasure/derived.hpp>
0035 #include <boost/type_erasure/rebind_any.hpp>
0036 #include <boost/type_erasure/param.hpp>
0037 #include <boost/type_erasure/is_placeholder.hpp>
0038 #include <boost/type_erasure/call.hpp>
0039 #include <boost/type_erasure/concept_interface.hpp>
0040
0041 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || \
0042 defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || \
0043 defined(BOOST_TYPE_ERASURE_DOXYGEN) || \
0044 BOOST_WORKAROUND(BOOST_MSVC, == 1800)
0045
0046 namespace boost {
0047 namespace type_erasure {
0048 namespace detail {
0049
0050 template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_TYPE_ERASURE_MAX_ARITY, class T, void)>
0051 struct first_placeholder {
0052 typedef typename ::boost::mpl::eval_if<is_placeholder<T0>,
0053 ::boost::mpl::identity<T0>,
0054 first_placeholder<BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_TYPE_ERASURE_MAX_ARITY, T)>
0055 >::type type;
0056 };
0057
0058 template<>
0059 struct first_placeholder<> {};
0060
0061 template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_TYPE_ERASURE_MAX_ARITY, class T, void)>
0062 struct first_placeholder_index :
0063 ::boost::mpl::eval_if<is_placeholder<T0>,
0064 ::boost::mpl::int_<0>,
0065 ::boost::mpl::next<first_placeholder_index<BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_TYPE_ERASURE_MAX_ARITY, T)> >
0066 >::type
0067 {};
0068
0069 }
0070 }
0071 }
0072
0073
0074 #define BOOST_TYPE_ERASURE_FREE_QUALIFIED_ID(seq, N) \
0075 BOOST_TYPE_ERASURE_QUALIFIED_NAME(seq)<R(BOOST_PP_ENUM_PARAMS(N, T))>
0076
0077
0078 #define BOOST_TYPE_ERASURE_FREE_UNQUALIFIED_PARAM_TYPE(z, n, data) \
0079 typename ::boost::remove_cv<typename ::boost::remove_reference<BOOST_PP_CAT(T, n)>::type>::type
0080
0081
0082 #define BOOST_TYPE_ERASURE_FREE_PARAM_TYPE(z, n, data) \
0083 typename ::boost::mpl::eval_if_c<(_boost_type_erasure_free_p_idx::value == n), \
0084 ::boost::type_erasure::detail::maybe_const_this_param<BOOST_PP_CAT(T, n), Base>, \
0085 ::boost::type_erasure::as_param<Base, BOOST_PP_CAT(T, n)> \
0086 >::type BOOST_PP_CAT(t, n)
0087
0088 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
0089
0090
0091 #define BOOST_TYPE_ERASURE_FREE_FORWARD_I(z, n, data) ::std::forward<BOOST_PP_CAT(T, n)>(BOOST_PP_CAT(t, n))
0092
0093 #define BOOST_TYPE_ERASURE_FREE_FORWARD(n) BOOST_PP_ENUM(n, BOOST_TYPE_ERASURE_FREE_FORWARD_I, ~)
0094
0095 #define BOOST_TYPE_ERASURE_FREE_FORWARD_PARAM_I(z, n, data) \
0096 ::std::forward<typename ::boost::mpl::eval_if_c<(_boost_type_erasure_free_p_idx::value == n), \
0097 ::boost::type_erasure::detail::maybe_const_this_param<BOOST_PP_CAT(T, n), Base>, \
0098 ::boost::type_erasure::as_param<Base, BOOST_PP_CAT(T, n)> \
0099 >::type>(BOOST_PP_CAT(t, n))
0100
0101 #else
0102
0103 #define BOOST_TYPE_ERASURE_FREE_FORWARD(n) BOOST_PP_ENUM_PARAMS(n, t)
0104 #define BOOST_TYPE_ERASURE_FREE_FORWARD_PARAM_I(z, n, data) BOOST_PP_CAT(t, n)
0105
0106 #endif
0107
0108
0109 #define BOOST_TYPE_ERASURE_FREE_II(qual_name, concept_name, function_name, N) \
0110 BOOST_TYPE_ERASURE_OPEN_NAMESPACE(qual_name) \
0111 \
0112 template<class Sig> \
0113 struct concept_name; \
0114 \
0115 template<class R BOOST_PP_ENUM_TRAILING_PARAMS(N, class T)> \
0116 struct concept_name<R(BOOST_PP_ENUM_PARAMS(N, T))> { \
0117 static R apply(BOOST_PP_ENUM_BINARY_PARAMS(N, T, t)) \
0118 { return function_name(BOOST_TYPE_ERASURE_FREE_FORWARD(N)); } \
0119 }; \
0120 \
0121 template<BOOST_PP_ENUM_PARAMS(N, class T)> \
0122 struct concept_name<void(BOOST_PP_ENUM_PARAMS(N, T))> { \
0123 static void apply(BOOST_PP_ENUM_BINARY_PARAMS(N, T, t)) \
0124 { function_name(BOOST_TYPE_ERASURE_FREE_FORWARD(N)); } \
0125 }; \
0126 \
0127 BOOST_TYPE_ERASURE_CLOSE_NAMESPACE(qual_name) \
0128 \
0129 namespace boost { \
0130 namespace type_erasure { \
0131 \
0132 template<class R BOOST_PP_ENUM_TRAILING_PARAMS(N, class T), class Base> \
0133 struct concept_interface< \
0134 BOOST_TYPE_ERASURE_FREE_QUALIFIED_ID(qual_name, N), \
0135 Base, \
0136 typename ::boost::type_erasure::detail::first_placeholder< \
0137 BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_FREE_UNQUALIFIED_PARAM_TYPE, ~)>::type \
0138 > : Base { \
0139 typedef typename ::boost::type_erasure::detail::first_placeholder_index< \
0140 BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_FREE_UNQUALIFIED_PARAM_TYPE, ~)>::type \
0141 _boost_type_erasure_free_p_idx; \
0142 friend typename ::boost::type_erasure::rebind_any<Base, R>::type function_name( \
0143 BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_FREE_PARAM_TYPE, ~)) \
0144 { \
0145 return ::boost::type_erasure::call( \
0146 BOOST_TYPE_ERASURE_FREE_QUALIFIED_ID(qual_name, N)() \
0147 BOOST_PP_ENUM_TRAILING(N, BOOST_TYPE_ERASURE_FREE_FORWARD_PARAM_I, ~)); \
0148 } \
0149 }; \
0150 \
0151 } \
0152 }
0153
0154
0155 #define BOOST_TYPE_ERASURE_FREE_I(namespace_name, concept_name, function_name, N)\
0156 BOOST_TYPE_ERASURE_FREE_II(namespace_name, concept_name, function_name, N)
0157
0158 #ifdef BOOST_TYPE_ERASURE_DOXYGEN
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199 #define BOOST_TYPE_ERASURE_FREE(concept_name, function_name)
0200
0201 #else
0202
0203 #define BOOST_TYPE_ERASURE_FREE(qualified_name, function_name, N) \
0204 BOOST_TYPE_ERASURE_FREE_I( \
0205 qualified_name, \
0206 BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(qualified_name)), qualified_name), \
0207 function_name, \
0208 N)
0209
0210 #endif
0211
0212 #else
0213
0214 namespace boost {
0215 namespace type_erasure {
0216
0217 template<int... N>
0218 struct index_list {};
0219
0220 namespace detail {
0221
0222 template<class... T>
0223 struct first_placeholder;
0224
0225 template<class T0, class... T>
0226 struct first_placeholder<T0, T...> {
0227 typedef typename ::boost::mpl::eval_if<is_placeholder<T0>,
0228 ::boost::mpl::identity<T0>,
0229 first_placeholder<T...>
0230 >::type type;
0231 };
0232
0233 template<>
0234 struct first_placeholder<> {};
0235
0236 template<class... T>
0237 struct first_placeholder_index;
0238
0239 template<class T0, class... T>
0240 struct first_placeholder_index<T0, T...> :
0241 ::boost::mpl::eval_if<is_placeholder<T0>,
0242 ::boost::mpl::int_<0>,
0243 ::boost::mpl::next<first_placeholder_index<T...> >
0244 >::type
0245 {};
0246
0247 template<class Sig>
0248 struct transform_free_signature;
0249
0250 template<class T, int N>
0251 struct push_back_index;
0252
0253 template<int... N, int X>
0254 struct push_back_index<index_list<N...>, X>
0255 {
0256 typedef index_list<N..., X> type;
0257 };
0258
0259 template<int N>
0260 struct make_index_list {
0261 typedef typename push_back_index<
0262 typename make_index_list<N-1>::type,
0263 N-1
0264 >::type type;
0265 };
0266
0267 template<>
0268 struct make_index_list<0> {
0269 typedef index_list<> type;
0270 };
0271
0272 #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && \
0273 !defined(BOOST_NO_CXX11_DECLTYPE)
0274
0275 template<int N>
0276 using make_index_list_t = typename ::boost::type_erasure::detail::make_index_list<N>::type;
0277
0278 #if BOOST_WORKAROUND(BOOST_MSVC, == 1900)
0279
0280 template<class... T>
0281 struct first_placeholder_index_ :
0282 ::boost::type_erasure::detail::first_placeholder_index<
0283 ::boost::remove_cv_t< ::boost::remove_reference_t<T> >...
0284 >
0285 {};
0286 template<class... T>
0287 using first_placeholder_index_t =
0288 typename ::boost::type_erasure::detail::first_placeholder_index_<T...>::type;
0289
0290 #else
0291
0292 template<class... T>
0293 using first_placeholder_index_t =
0294 typename ::boost::type_erasure::detail::first_placeholder_index<
0295 ::boost::remove_cv_t< ::boost::remove_reference_t<T> >...
0296 >::type;
0297
0298 #endif
0299
0300 template<class Base, class Tn, int I, class... T>
0301 using free_param_t =
0302 typename ::boost::mpl::eval_if_c<(::boost::type_erasure::detail::first_placeholder_index_t<T...>::value == I),
0303 ::boost::type_erasure::detail::maybe_const_this_param<Tn, Base>, \
0304 ::boost::type_erasure::as_param<Base, Tn>
0305 >::type;
0306
0307 template<class Sig, class ID>
0308 struct free_interface_chooser
0309 {
0310 template<class Base, template<class> class C, template<class...> class F>
0311 using apply = Base;
0312 };
0313
0314 template<class R, class... A>
0315 struct free_interface_chooser<
0316 R(A...),
0317 typename ::boost::type_erasure::detail::first_placeholder<
0318 ::boost::remove_cv_t< ::boost::remove_reference_t<A> >...>::type>
0319 {
0320 template<class Base, template<class> class C, template<class...> class F>
0321 using apply = F<R(A...), Base,
0322 ::boost::type_erasure::detail::make_index_list_t<sizeof...(A)> >;
0323 };
0324
0325 template<class Sig, template<class> class C, template<class...> class F>
0326 struct free_choose_interface {
0327 template<class Concept, class Base, class ID>
0328 using apply = typename free_interface_chooser<Sig, ID>::template apply<Base, C, F>;
0329 };
0330
0331
0332 #define BOOST_TYPE_ERASURE_FREE_I(concept_name, function_name) \
0333 template<class Sig> \
0334 struct concept_name; \
0335 \
0336 namespace boost_type_erasure_impl { \
0337 \
0338 template<class Sig, class Base, class Idx> \
0339 struct concept_name ## _free_interface; \
0340 template<class R, class... T, class Base, int... I> \
0341 struct concept_name ## _free_interface<R(T...), Base, ::boost::type_erasure::index_list<I...> > : Base {\
0342 friend ::boost::type_erasure::rebind_any_t<Base, R> \
0343 function_name( \
0344 ::boost::type_erasure::detail::free_param_t<Base, T, I, T...>... t) \
0345 { \
0346 return ::boost::type_erasure::call( \
0347 concept_name<R(T...)>(), \
0348 std::forward< ::boost::type_erasure::detail::free_param_t<Base, T, I, T...> >(t)...);\
0349 } \
0350 }; \
0351 \
0352 template<class Sig> \
0353 struct concept_name ## free; \
0354 \
0355 template<class R, class... T> \
0356 struct concept_name ## free<R(T...)> { \
0357 static R apply(T... t) \
0358 { return function_name(std::forward<T>(t)...); } \
0359 }; \
0360 \
0361 template<class... T> \
0362 struct concept_name ## free<void(T...)> { \
0363 static void apply(T... t) \
0364 { function_name(std::forward<T>(t)...); } \
0365 }; \
0366 \
0367 } \
0368 \
0369 template<class Sig> \
0370 struct concept_name : \
0371 boost_type_erasure_impl::concept_name##free<Sig> \
0372 {}; \
0373 \
0374 template<class Sig> \
0375 ::boost::type_erasure::detail::free_choose_interface<Sig, concept_name, \
0376 boost_type_erasure_impl::concept_name ## _free_interface> \
0377 boost_type_erasure_find_interface(concept_name<Sig>);
0378
0379 #define BOOST_TYPE_ERASURE_FREE_SIMPLE(name, ...) \
0380 BOOST_TYPE_ERASURE_FREE_I(has_ ## name, name)
0381
0382 #define BOOST_TYPE_ERASURE_FREE_NS_I(concept_name, name) \
0383 BOOST_TYPE_ERASURE_FREE_I(concept_name, name)
0384
0385 #define BOOST_TYPE_ERASURE_FREE_NS(concept_name, name) \
0386 BOOST_TYPE_ERASURE_OPEN_NAMESPACE(concept_name) \
0387 BOOST_TYPE_ERASURE_FREE_NS_I(BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(concept_name)), concept_name), name) \
0388 BOOST_TYPE_ERASURE_CLOSE_NAMESPACE(concept_name)
0389
0390 #define BOOST_TYPE_ERASURE_FREE_NAMED(concept_name, name, ...) \
0391 BOOST_PP_IF(BOOST_PP_IS_BEGIN_PARENS(concept_name), \
0392 BOOST_TYPE_ERASURE_FREE_NS, \
0393 BOOST_TYPE_ERASURE_FREE_I) \
0394 (concept_name, name)
0395
0396 #define BOOST_TYPE_ERASURE_FREE_CAT(x, y) x y
0397
0398 #define BOOST_TYPE_ERASURE_FREE(name, ...) \
0399 BOOST_TYPE_ERASURE_FREE_CAT( \
0400 BOOST_PP_IF(BOOST_VMD_IS_EMPTY(__VA_ARGS__), \
0401 BOOST_TYPE_ERASURE_FREE_SIMPLE, \
0402 BOOST_TYPE_ERASURE_FREE_NAMED), \
0403 (name, __VA_ARGS__))
0404
0405 #else
0406
0407
0408 #define BOOST_TYPE_ERASURE_FREE_II(qual_name, concept_name, function_name) \
0409 BOOST_TYPE_ERASURE_OPEN_NAMESPACE(qual_name) \
0410 \
0411 template<class Sig> \
0412 struct concept_name; \
0413 \
0414 template<class R, class... T> \
0415 struct concept_name<R(T...)> { \
0416 static R apply(T... t) \
0417 { return function_name(std::forward<T>(t)...); } \
0418 }; \
0419 \
0420 template<class... T> \
0421 struct concept_name<void(T...)> { \
0422 static void apply(T... t) \
0423 { function_name(std::forward<T>(t)...); } \
0424 }; \
0425 \
0426 BOOST_TYPE_ERASURE_CLOSE_NAMESPACE(qual_name) \
0427 \
0428 namespace boost { \
0429 namespace type_erasure { \
0430 \
0431 template<class Sig, class Base, class Idx> \
0432 struct inject ## concept_name; \
0433 template<class R, class... T, class Base, int... I> \
0434 struct inject ## concept_name<R(T...), Base, index_list<I...> > : Base {\
0435 typedef typename ::boost::type_erasure::detail::first_placeholder_index< \
0436 typename ::boost::remove_cv< \
0437 typename ::boost::remove_reference<T>::type \
0438 >::type... \
0439 >::type _boost_type_erasure_free_p_idx; \
0440 friend typename ::boost::type_erasure::rebind_any<Base, R>::type\
0441 function_name( \
0442 typename ::boost::mpl::eval_if_c<(_boost_type_erasure_free_p_idx::value == I), \
0443 ::boost::type_erasure::detail::maybe_const_this_param<T, Base>, \
0444 ::boost::type_erasure::as_param<Base, T> \
0445 >::type... t) \
0446 { \
0447 return ::boost::type_erasure::call( \
0448 BOOST_TYPE_ERASURE_QUALIFIED_NAME(qual_name)<R(T...)>(),\
0449 std::forward<typename ::boost::mpl::eval_if_c<(_boost_type_erasure_free_p_idx::value == I), \
0450 ::boost::type_erasure::detail::maybe_const_this_param<T, Base>, \
0451 ::boost::type_erasure::as_param<Base, T> \
0452 >::type>(t)...); \
0453 } \
0454 }; \
0455 \
0456 template<class R, class... T, class Base> \
0457 struct concept_interface< \
0458 BOOST_TYPE_ERASURE_QUALIFIED_NAME(qual_name)<R(T...)>, \
0459 Base, \
0460 typename ::boost::type_erasure::detail::first_placeholder< \
0461 typename ::boost::remove_cv<typename ::boost::remove_reference<T>::type>::type...>::type \
0462 > : inject ## concept_name<R(T...), Base, typename ::boost::type_erasure::detail::make_index_list<sizeof...(T)>::type>\
0463 {}; \
0464 \
0465 } \
0466 }
0467
0468
0469
0470 #define BOOST_TYPE_ERASURE_FREE_I(namespace_name, concept_name, function_name) \
0471 BOOST_TYPE_ERASURE_FREE_II(namespace_name, concept_name, function_name)
0472
0473 #define BOOST_TYPE_ERASURE_FREE(qualified_name, function_name, ...) \
0474 BOOST_TYPE_ERASURE_FREE_I( \
0475 qualified_name, \
0476 BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(qualified_name)), qualified_name), \
0477 function_name)
0478
0479 #endif
0480
0481 }
0482 }
0483 }
0484
0485 #endif
0486
0487 #endif