free.hpp 22 KB

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