member11.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. // Boost.TypeErasure library
  2. //
  3. // Copyright 2018 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_DETAIL_MEMBER11_HPP_INCLUDED
  11. #define BOOST_TYPE_ERASURE_DETAIL_MEMBER11_HPP_INCLUDED
  12. #include <boost/config.hpp>
  13. #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && \
  14. !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
  15. !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
  16. !defined(BOOST_NO_CXX11_DECLTYPE) && \
  17. !BOOST_WORKAROUND(BOOST_MSVC, == 1800)
  18. #include <boost/preprocessor/cat.hpp>
  19. #include <boost/preprocessor/control/if.hpp>
  20. #include <boost/preprocessor/punctuation/is_begin_parens.hpp>
  21. #include <boost/vmd/is_empty.hpp>
  22. #include <boost/type_traits/remove_reference.hpp>
  23. #include <boost/type_traits/remove_cv.hpp>
  24. #include <boost/mpl/if.hpp>
  25. #include <boost/type_erasure/detail/const.hpp>
  26. #include <boost/type_erasure/detail/macro.hpp>
  27. #include <boost/type_erasure/rebind_any.hpp>
  28. #include <boost/type_erasure/param.hpp>
  29. #include <boost/type_erasure/is_placeholder.hpp>
  30. #include <boost/type_erasure/call.hpp>
  31. namespace boost {
  32. namespace type_erasure {
  33. namespace detail {
  34. template<class P, template<class ...> class interface, class Sig, class Concept, class Base, class ID>
  35. using choose_member_interface = typename ::boost::mpl::if_c< ::boost::is_reference<P>::value,
  36. typename ::boost::mpl::if_c< ::boost::type_erasure::detail::is_non_const_ref<P>::value,
  37. interface<Sig, Concept, Base, const ID>,
  38. Base
  39. >::type,
  40. interface<Sig, Concept, Base, ID>
  41. >::type;
  42. struct dummy {};
  43. template<class Sig>
  44. struct choose_member_impl;
  45. template<class R, class C, class... T>
  46. struct choose_member_impl<R (C::*)(T...) const>
  47. {
  48. template<class P, template<class> class M, template<class,class> class S>
  49. using apply = ::boost::mpl::vector1<S<R(T...), const P> >;
  50. };
  51. template<class R, class C, class... T>
  52. struct choose_member_impl<R (C::*)(T...)>
  53. {
  54. template<class P, template<class> class M, template<class,class> class S>
  55. using apply = M<R(P&, T...)>;
  56. };
  57. template<class Sig, class P, template<class> class M, template<class, class> class Self>
  58. using choose_member_impl_t =
  59. typename ::boost::type_erasure::detail::choose_member_impl<
  60. Sig (::boost::type_erasure::detail::dummy::*)
  61. >::template apply<P, M, Self>;
  62. template<class Sig, class T, class ID>
  63. struct member_interface_chooser
  64. {
  65. template<class Base, template<class, class> class C, template<class...> class M>
  66. using apply = Base;
  67. };
  68. template<class R, class T, class... A>
  69. struct member_interface_chooser<R(A...), T, T>
  70. {
  71. template<class Base, template<class, class> class C, template<class...> class M>
  72. using apply = ::boost::type_erasure::detail::choose_member_interface<
  73. ::boost::type_erasure::placeholder_of_t<Base>,
  74. M,
  75. R(A...), C<R(A...), T>, Base, T>;
  76. };
  77. template<class R, class T, class... A>
  78. struct member_interface_chooser<R(A...), const T, T>
  79. {
  80. template<class Base, template<class, class> class C, template<class...> class M>
  81. using apply = M<R(A...), C<R(A...), const T>, Base, const T>;
  82. };
  83. template<class Sig, class T, template<class, class> class C, template<class...> class M>
  84. struct member_choose_interface
  85. {
  86. template<class Concept, class Base, class ID>
  87. using apply = typename ::boost::type_erasure::detail::member_interface_chooser<Sig, T, ID>::template apply<Base, C, M>;
  88. };
  89. }
  90. }
  91. }
  92. #define BOOST_TYPE_ERASURE_MEMBER_I(concept_name, function_name) \
  93. template<class Sig, class T = ::boost::type_erasure::_self> \
  94. struct concept_name; \
  95. \
  96. namespace boost_type_erasure_impl { \
  97. \
  98. template<class Sig, class T> \
  99. using concept_name ## self = concept_name<Sig, T>; \
  100. \
  101. template<class Sig, class Concept, class Base, class ID, class Enable = void>\
  102. struct concept_name ## _member_interface; \
  103. \
  104. template<class R, class... A, class Concept, class Base, class ID, class V> \
  105. struct concept_name ## _member_interface<R(A...), Concept, Base, ID, V> : Base\
  106. { \
  107. typedef void _boost_type_erasure_has_member ## function_name; \
  108. ::boost::type_erasure::rebind_any_t<Base, R> function_name(::boost::type_erasure::as_param_t<Base, A>... a)\
  109. { return ::boost::type_erasure::call(Concept(), *this, std::forward<A>(a)...); }\
  110. }; \
  111. \
  112. template<class R, class... A, class Concept, class Base, class ID> \
  113. struct concept_name ## _member_interface<R(A...), Concept, Base, ID, \
  114. typename Base::_boost_type_erasure_has_member ## function_name> : Base \
  115. { \
  116. using Base::function_name; \
  117. ::boost::type_erasure::rebind_any_t<Base, R> function_name(::boost::type_erasure::as_param_t<Base, A>... a)\
  118. { return ::boost::type_erasure::call(Concept(), *this, std::forward<A>(a)...); }\
  119. }; \
  120. \
  121. template<class R, class... A, class Concept, class Base, class ID, class V> \
  122. struct concept_name ## _member_interface<R(A...), Concept, Base, const ID, V> : Base\
  123. { \
  124. typedef void _boost_type_erasure_has_member ## function_name; \
  125. ::boost::type_erasure::rebind_any_t<Base, R> function_name(::boost::type_erasure::as_param_t<Base, A>... a) const\
  126. { return ::boost::type_erasure::call(Concept(), *this, std::forward<A>(a)...); }\
  127. }; \
  128. \
  129. template<class R, class... A, class Concept, class Base, class ID> \
  130. struct concept_name ## _member_interface<R(A...), Concept, Base, const ID, \
  131. typename Base::_boost_type_erasure_has_member ## function_name> : Base \
  132. { \
  133. using Base::function_name; \
  134. ::boost::type_erasure::rebind_any_t<Base, R> function_name(::boost::type_erasure::as_param_t<Base, A>... a) const\
  135. { return ::boost::type_erasure::call(Concept(), *this, std::forward<A>(a)...); }\
  136. }; \
  137. \
  138. template<class Sig> \
  139. struct concept_name ## member; \
  140. \
  141. template<class R, class T0, class... T> \
  142. struct concept_name ## member<R(T0, T...)> { \
  143. static R apply(T0 t0, T... t) \
  144. { return t0.function_name(std::forward<T>(t)...); } \
  145. }; \
  146. \
  147. template<class T0, class... T> \
  148. struct concept_name ## member<void(T0, T...)> { \
  149. static void apply(T0 t0, T... t) \
  150. { t0.function_name(std::forward<T>(t)...); } \
  151. }; \
  152. \
  153. } \
  154. \
  155. template<class Sig, class T> \
  156. struct concept_name : \
  157. ::boost::type_erasure::detail::choose_member_impl_t<Sig, T, \
  158. boost_type_erasure_impl::concept_name##member, \
  159. boost_type_erasure_impl::concept_name##self \
  160. > \
  161. {}; \
  162. \
  163. template<class Sig, class T> \
  164. ::boost::type_erasure::detail::member_choose_interface<Sig, T, concept_name,\
  165. boost_type_erasure_impl::concept_name ## _member_interface> \
  166. boost_type_erasure_find_interface(concept_name<Sig, T>);
  167. #define BOOST_TYPE_ERASURE_MEMBER_SIMPLE(name, ...) \
  168. BOOST_TYPE_ERASURE_MEMBER_I(has_ ## name, name)
  169. #define BOOST_TYPE_ERASURE_MEMBER_NS_I(concept_name, name) \
  170. BOOST_TYPE_ERASURE_MEMBER_I(concept_name, name)
  171. #define BOOST_TYPE_ERASURE_MEMBER_NS(concept_name, name) \
  172. BOOST_TYPE_ERASURE_OPEN_NAMESPACE(concept_name) \
  173. BOOST_TYPE_ERASURE_MEMBER_NS_I(BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(concept_name)), concept_name), name) \
  174. BOOST_TYPE_ERASURE_CLOSE_NAMESPACE(concept_name)
  175. #define BOOST_TYPE_ERASURE_MEMBER_NAMED(concept_name, name, ...) \
  176. BOOST_PP_IF(BOOST_PP_IS_BEGIN_PARENS(concept_name), \
  177. BOOST_TYPE_ERASURE_MEMBER_NS, \
  178. BOOST_TYPE_ERASURE_MEMBER_I) \
  179. (concept_name, name)
  180. #define BOOST_TYPE_ERASURE_MEMBER_CAT(x, y) x y
  181. #define BOOST_TYPE_ERASURE_MEMBER(name, ...) \
  182. BOOST_TYPE_ERASURE_MEMBER_CAT( \
  183. BOOST_PP_IF(BOOST_VMD_IS_EMPTY(__VA_ARGS__), \
  184. BOOST_TYPE_ERASURE_MEMBER_SIMPLE, \
  185. BOOST_TYPE_ERASURE_MEMBER_NAMED), \
  186. (name, __VA_ARGS__))
  187. #endif
  188. #endif