member.hpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. // Boost.TypeErasure library
  2. //
  3. // Copyright 2012-2013 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_MEMBER_HPP_INCLUDED
  11. #define BOOST_TYPE_ERASURE_MEMBER_HPP_INCLUDED
  12. #include <boost/type_erasure/detail/member11.hpp>
  13. #ifndef BOOST_TYPE_ERASURE_MEMBER
  14. #include <boost/detail/workaround.hpp>
  15. #include <boost/preprocessor/cat.hpp>
  16. #include <boost/preprocessor/dec.hpp>
  17. #include <boost/preprocessor/comma_if.hpp>
  18. #include <boost/preprocessor/repetition/enum.hpp>
  19. #include <boost/preprocessor/repetition/enum_trailing.hpp>
  20. #include <boost/preprocessor/repetition/enum_params.hpp>
  21. #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
  22. #include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
  23. #include <boost/preprocessor/seq/size.hpp>
  24. #include <boost/preprocessor/seq/elem.hpp>
  25. #include <boost/preprocessor/tuple/elem.hpp>
  26. #include <boost/type_erasure/detail/macro.hpp>
  27. #include <boost/type_erasure/detail/const.hpp>
  28. #include <boost/type_erasure/rebind_any.hpp>
  29. #include <boost/type_erasure/placeholder.hpp>
  30. #include <boost/type_erasure/call.hpp>
  31. #include <boost/type_erasure/concept_interface.hpp>
  32. /** INTERNAL ONLY */
  33. #define BOOST_TYPE_ERASURE_MEMBER_ARG(z, n, data) \
  34. typename ::boost::type_erasure::as_param<Base, BOOST_PP_CAT(A, n)>::type BOOST_PP_CAT(a, n)
  35. #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || \
  36. defined(BOOST_TYPE_ERASURE_DOXYGEN) || \
  37. BOOST_WORKAROUND(BOOST_MSVC, == 1800)
  38. /** INTERNAL ONLY */
  39. #define BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(seq, N) \
  40. BOOST_TYPE_ERASURE_QUALIFIED_NAME(seq)<R(BOOST_PP_ENUM_PARAMS(N, A)), T>
  41. /** INTERNAL ONLY */
  42. #define BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, X) BOOST_PP_ENUM_TRAILING_PARAMS(N, X)
  43. /** INTERNAL ONLY */
  44. #define BOOST_TYPE_ERASURE_MEMBER_ENUM_PARAMS(N, X) BOOST_PP_ENUM_PARAMS(N, X)
  45. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  46. /** INTERNAL ONLY */
  47. #define BOOST_TYPE_ERASURE_MEMBER_FORWARD(z, n, data) ::std::forward<BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2, 0, data), n)>(BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2, 1, data), n))
  48. /** INTERNAL ONLY */
  49. #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, X, x) BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_MEMBER_FORWARD, (X, x))
  50. /** INTERNAL ONLY*/
  51. #define BOOST_TYPE_ERASURE_FORWARD_REBIND1(z, n, data) ::std::forward<typename ::boost::type_erasure::as_param<Base, BOOST_PP_CAT(A, n)>::type>(BOOST_PP_CAT(a, n))
  52. /** INTERNAL ONLY*/
  53. #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N) BOOST_PP_ENUM_TRAILING(N, BOOST_TYPE_ERASURE_FORWARD_REBIND1, ~)
  54. #else
  55. /** INTERNAL ONLY */
  56. #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, X, x) BOOST_PP_ENUM_PARAMS(N, x)
  57. /** INTERNAL ONLY*/
  58. #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N) BOOST_PP_ENUM_TRAILING_PARAMS(N, a)
  59. #endif
  60. /** INTERNAL ONLY */
  61. #define BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_PARAMS(N, X) BOOST_PP_ENUM_TRAILING_PARAMS(N, X)
  62. /** INTERNAL ONLY */
  63. #define BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_BINARY_PARAMS(N, X, x) BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, X, x)
  64. /** INTERNAL ONLY */
  65. #define BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N) BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_MEMBER_ARG, ~)
  66. #ifdef BOOST_TYPE_ERASURE_DOXYGEN
  67. /**
  68. * \brief Defines a primitive concept for a member function.
  69. *
  70. * \param concept_name is the name of the concept to declare.
  71. * If it is omitted it defaults to <code>has_ ## member</code>
  72. * \param member is the name of the member function.
  73. *
  74. * The declaration of the concept is
  75. * \code
  76. * template<class Sig, class T = _self>
  77. * struct concept_name;
  78. * \endcode
  79. * where @c Sig is a function type giving the
  80. * signature of the member function, and @c T is the
  81. * object type. @c T may be const-qualified for
  82. * const member functions. @c concept_name<R(A...) const, T>
  83. * is an alias for @c concept_name<R(A...), const T>.
  84. *
  85. * This macro can only be used at namespace scope.
  86. *
  87. * Example:
  88. *
  89. * \code
  90. * namespace boost {
  91. * BOOST_TYPE_ERASURE_MEMBER(push_back)
  92. * }
  93. * typedef boost::has_push_back<void(int)> push_back_concept;
  94. * \endcode
  95. *
  96. * The concept defined by this function may be specialized to
  97. * provide a concept_map. The class object will be passed by
  98. * reference as the first parameter.
  99. *
  100. * \code
  101. * template<>
  102. * struct has_push_back<void(int), std::list<int> > {
  103. * static void apply(std::list<int>& l, int i) { l.push_back(i); }
  104. * };
  105. * \endcode
  106. *
  107. * In C++03, the macro can only be used in the global namespace and
  108. * is defined as:
  109. *
  110. * \code
  111. * #define BOOST_TYPE_ERASURE_MEMBER(qualified_name, member, N)
  112. * \endcode
  113. *
  114. * Example:
  115. *
  116. * \code
  117. * BOOST_TYPE_ERASURE_MEMBER((boost)(has_push_back), push_back, 1)
  118. * typedef boost::has_push_back<void(int), _self> push_back_concept;
  119. * \endcode
  120. *
  121. * For backwards compatibility, this form is always accepted.
  122. */
  123. #define BOOST_TYPE_ERASURE_MEMBER(concept_name, member) /**/
  124. #else
  125. #define BOOST_TYPE_ERASURE_MEMBER(qualified_name, member, N) \
  126. BOOST_TYPE_ERASURE_MEMBER_I( \
  127. qualified_name, \
  128. BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(qualified_name)), qualified_name), \
  129. member, \
  130. N)
  131. #endif
  132. #else
  133. /** INTERNAL ONLY */
  134. #define BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(seq, N) \
  135. BOOST_TYPE_ERASURE_QUALIFIED_NAME(seq)<R(A...), T>
  136. #define BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, X) , class... A
  137. #define BOOST_TYPE_ERASURE_MEMBER_ENUM_PARAMS(N, X) X...
  138. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  139. # define BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, X, x) ::std::forward<X>(x)...
  140. # define BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N) , ::std::forward<typename ::boost::type_erasure::as_param<Base, A>::type>(a)...
  141. #else
  142. # define BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, X, x) x...
  143. # define BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N) , a...
  144. #endif
  145. #define BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_PARAMS(N, X) , X...
  146. #define BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_BINARY_PARAMS(N, X, x) , X... x
  147. #define BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N) typename ::boost::type_erasure::as_param<Base, A>::type... a
  148. #define BOOST_TYPE_ERASURE_MEMBER(qualified_name, member, ...) \
  149. BOOST_TYPE_ERASURE_MEMBER_I( \
  150. qualified_name, \
  151. BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(qualified_name)), qualified_name), \
  152. member, \
  153. N)
  154. #endif
  155. /** INTERNAL ONLY */
  156. #define BOOST_TYPE_ERASURE_MEMBER_II(qual_name, concept_name, member, N) \
  157. BOOST_TYPE_ERASURE_OPEN_NAMESPACE(qual_name) \
  158. template<class Sig, class T = ::boost::type_erasure::_self> \
  159. struct concept_name; \
  160. template<class R BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A), class T> \
  161. struct concept_name<R(BOOST_TYPE_ERASURE_MEMBER_ENUM_PARAMS(N, A)), T> { \
  162. static R apply(T& t BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_BINARY_PARAMS(N, A, a)) \
  163. { return t.member(BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, A, a)); } \
  164. }; \
  165. template<class T BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A)> \
  166. struct concept_name<void(BOOST_TYPE_ERASURE_MEMBER_ENUM_PARAMS(N, A)), T> { \
  167. static void apply(T& t BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_BINARY_PARAMS(N, A, a)) \
  168. { t.member(BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, A, a)); } \
  169. }; \
  170. BOOST_TYPE_ERASURE_CLOSE_NAMESPACE(qual_name) \
  171. namespace boost { \
  172. namespace type_erasure { \
  173. template< \
  174. class R BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A), \
  175. class T, class Base, class Enable> \
  176. struct concept_interface< \
  177. BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N), \
  178. Base, \
  179. typename ::boost::enable_if< \
  180. ::boost::type_erasure::detail::should_be_non_const<T, Base>, \
  181. typename ::boost::remove_const<T>::type \
  182. >::type, \
  183. Enable \
  184. > : Base \
  185. { \
  186. typedef void BOOST_PP_CAT(_boost_type_erasure_has_member, member); \
  187. typename rebind_any<Base, R>::type member( \
  188. BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N)) \
  189. { \
  190. return ::boost::type_erasure::call( \
  191. BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N)(), \
  192. *this BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N)); \
  193. } \
  194. }; \
  195. template< \
  196. class R BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A), \
  197. class T, class Base, class Enable> \
  198. struct concept_interface< \
  199. BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N), \
  200. Base, \
  201. typename ::boost::enable_if< \
  202. ::boost::type_erasure::detail::should_be_const<T, Base>, \
  203. typename ::boost::remove_const<T>::type \
  204. >::type, \
  205. Enable \
  206. > : Base \
  207. { \
  208. typedef void BOOST_PP_CAT(_boost_type_erasure_has_member, member); \
  209. typename rebind_any<Base, R>::type member( \
  210. BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N)) const \
  211. { \
  212. return ::boost::type_erasure::call( \
  213. BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N)(), \
  214. *this BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N)); \
  215. } \
  216. }; \
  217. template<class R BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A), class T, class Base> \
  218. struct concept_interface< \
  219. BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N), \
  220. Base, \
  221. typename ::boost::enable_if< \
  222. ::boost::type_erasure::detail::should_be_non_const<T, Base>, \
  223. typename ::boost::remove_const<T>::type \
  224. >::type, \
  225. typename Base::BOOST_PP_CAT(_boost_type_erasure_has_member, member)> : Base \
  226. { \
  227. using Base::member; \
  228. typename rebind_any<Base, R>::type member( \
  229. BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N)) \
  230. { \
  231. return ::boost::type_erasure::call( \
  232. BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N)(), \
  233. *this BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N)); \
  234. } \
  235. }; \
  236. template<class R BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A), class T, class Base> \
  237. struct concept_interface< \
  238. BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N), \
  239. Base, \
  240. typename ::boost::enable_if< \
  241. ::boost::type_erasure::detail::should_be_const<T, Base>, \
  242. typename ::boost::remove_const<T>::type \
  243. >::type, \
  244. typename Base::BOOST_PP_CAT(_boost_type_erasure_has_member, member)> : Base \
  245. { \
  246. using Base::member; \
  247. typename rebind_any<Base, R>::type member( \
  248. BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N)) const \
  249. { \
  250. return ::boost::type_erasure::call( \
  251. BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N)(), \
  252. *this BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N)); \
  253. } \
  254. }; \
  255. }}
  256. /** INTERNAL ONLY */
  257. #define BOOST_TYPE_ERASURE_MEMBER_I(namespace_name, concept_name, member, N)\
  258. BOOST_TYPE_ERASURE_MEMBER_II(namespace_name, concept_name, member, N)
  259. #endif
  260. #endif