check_match.hpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. // Boost.TypeErasure library
  2. //
  3. // Copyright 2011 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. #if !defined(BOOST_PP_IS_ITERATING)
  11. #ifndef BOOST_TYPE_ERASURE_CHECK_MATCH_HPP_INCLUDED
  12. #define BOOST_TYPE_ERASURE_CHECK_MATCH_HPP_INCLUDED
  13. #include <boost/mpl/vector.hpp>
  14. #include <boost/mpl/bool.hpp>
  15. #include <boost/mpl/is_sequence.hpp>
  16. #include <boost/mpl/find_if.hpp>
  17. #include <boost/mpl/not.hpp>
  18. #include <boost/mpl/end.hpp>
  19. #include <boost/type_traits/is_same.hpp>
  20. #include <boost/preprocessor/cat.hpp>
  21. #include <boost/preprocessor/iteration/iterate.hpp>
  22. #include <boost/preprocessor/repetition/repeat.hpp>
  23. #include <boost/preprocessor/repetition/enum_params.hpp>
  24. #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
  25. #include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
  26. #include <boost/type_erasure/detail/extract_concept.hpp>
  27. #include <boost/type_erasure/relaxed.hpp>
  28. #include <boost/type_erasure/detail/access.hpp>
  29. namespace boost {
  30. namespace type_erasure {
  31. #ifndef BOOST_TYPE_ERASURE_DOXYGEN
  32. template<class T>
  33. struct typeid_;
  34. template<class Concept>
  35. class binding;
  36. #endif
  37. namespace detail {
  38. template<class P, class T, class Table>
  39. bool maybe_check_table(const T& arg, const Table*& table, boost::mpl::true_)
  40. {
  41. if(table == 0) {
  42. table = &::boost::type_erasure::detail::access::table(arg);
  43. return true;
  44. } else {
  45. return table->template find< ::boost::type_erasure::typeid_<P> >()() ==
  46. ::boost::type_erasure::detail::access::table(arg).
  47. template find< ::boost::type_erasure::typeid_<P> >()();
  48. }
  49. }
  50. template<class P, class T, class Table>
  51. bool maybe_check_table(const T&, const Table*&, boost::mpl::false_)
  52. {
  53. return true;
  54. }
  55. template<class Concept, class T>
  56. struct should_check :
  57. boost::mpl::and_<
  58. ::boost::type_erasure::is_placeholder<T>,
  59. ::boost::type_erasure::is_relaxed<Concept>
  60. >
  61. {};
  62. }
  63. #ifdef BOOST_TYPE_ERASURE_DOXYGEN
  64. /**
  65. * If @ref relaxed is in @c Concept, checks whether the
  66. * arguments to @c f match the types specified by
  67. * @c binding. If @ref relaxed is not in @c Concept,
  68. * returns true. If @c binding is not specified, it will
  69. * be deduced from the arguments.
  70. */
  71. template<class Concept, class Op, class... U>
  72. bool check_match(const binding<Concept>& binding_arg, const Op& f, U&&... args);
  73. /**
  74. * \overload
  75. */
  76. template<class Op, class... U>
  77. bool check_match(const Op& f, U&&... args);
  78. #else
  79. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  80. namespace detail {
  81. template<class Concept, class R>
  82. bool check_table(const ::boost::type_erasure::binding<Concept>* /*t*/, R(*)())
  83. {
  84. return true;
  85. }
  86. template<class Concept, class R, class T0, class... T, class U0, class... U>
  87. bool check_table(
  88. const ::boost::type_erasure::binding<Concept>* t,
  89. R(*)(T0, T...),
  90. const U0& arg0,
  91. const U&... arg)
  92. {
  93. typedef typename ::boost::remove_cv<
  94. typename ::boost::remove_reference<T0>::type
  95. >::type t0;
  96. if(!::boost::type_erasure::detail::maybe_check_table<t0>(
  97. arg0,
  98. t,
  99. ::boost::type_erasure::detail::should_check<Concept, t0>()))
  100. return false;
  101. return check_table(t, static_cast<void(*)(T...)>(0), arg...);
  102. }
  103. }
  104. template<class Concept, class Op, class... U>
  105. bool check_match(
  106. const ::boost::type_erasure::binding<Concept>& table,
  107. const Op&,
  108. U&&... arg)
  109. {
  110. return ::boost::type_erasure::detail::check_table(
  111. &table,
  112. static_cast<typename ::boost::type_erasure::detail::get_signature<Op>::type*>(0),
  113. arg...);
  114. }
  115. #ifndef BOOST_TYPE_ERASURE_USE_MP11
  116. template<
  117. class Op,
  118. class... U
  119. >
  120. bool check_match(
  121. const Op&,
  122. U&&... arg)
  123. {
  124. const ::boost::type_erasure::binding<
  125. typename ::boost::type_erasure::detail::extract_concept<
  126. typename ::boost::type_erasure::detail::get_signature<Op>::type, U...>::type>* p = 0;
  127. return ::boost::type_erasure::detail::check_table(
  128. p, static_cast<typename ::boost::type_erasure::detail::get_signature<Op>::type*>(0), arg...);
  129. }
  130. #else
  131. namespace detail {
  132. template<class T>
  133. struct get_args;
  134. template<class R, class ... T>
  135. struct get_args<R(T...)> { typedef ::boost::mp11::mp_list<T...> type; };
  136. template<class Sig>
  137. using get_args_t = typename get_args<Sig>::type;
  138. }
  139. template<
  140. class Op,
  141. class... U
  142. >
  143. bool check_match(
  144. const Op&,
  145. U&&... arg)
  146. {
  147. const ::boost::type_erasure::binding<
  148. ::boost::type_erasure::detail::extract_concept_t<
  149. ::boost::type_erasure::detail::get_args_t<
  150. typename ::boost::type_erasure::detail::get_signature<Op>::type
  151. >,
  152. ::boost::mp11::mp_list< ::boost::remove_reference_t<U>...> > >* p = 0;
  153. return ::boost::type_erasure::detail::check_table(
  154. p, static_cast<typename ::boost::type_erasure::detail::get_signature<Op>::type*>(0), arg...);
  155. }
  156. #endif
  157. #else
  158. #define BOOST_PP_FILENAME_1 <boost/type_erasure/check_match.hpp>
  159. #define BOOST_PP_ITERATION_LIMITS (0, BOOST_TYPE_ERASURE_MAX_ARITY)
  160. #include BOOST_PP_ITERATE()
  161. #endif
  162. #endif
  163. }
  164. }
  165. #endif
  166. #else
  167. namespace detail {
  168. #define N BOOST_PP_ITERATION()
  169. #define BOOST_TYPE_ERASURE_CHECK_TABLE(z, n, data) \
  170. typedef typename ::boost::remove_cv< \
  171. typename ::boost::remove_reference<BOOST_PP_CAT(T, n)>::type \
  172. >::type BOOST_PP_CAT(t, n); \
  173. if(!::boost::type_erasure::detail::maybe_check_table<BOOST_PP_CAT(t, n)>( \
  174. BOOST_PP_CAT(arg, n), \
  175. t, \
  176. ::boost::type_erasure::detail::should_check<Concept, BOOST_PP_CAT(t, n)>())) \
  177. return false;
  178. template<
  179. class Concept,
  180. class R
  181. BOOST_PP_ENUM_TRAILING_PARAMS(N, class T)
  182. BOOST_PP_ENUM_TRAILING_PARAMS(N, class U)>
  183. bool
  184. BOOST_PP_CAT(check_table, N)(
  185. const ::boost::type_erasure::binding<Concept>* t,
  186. R (*)(BOOST_PP_ENUM_PARAMS(N, T))
  187. BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, const U, &arg))
  188. {
  189. BOOST_PP_REPEAT(N, BOOST_TYPE_ERASURE_CHECK_TABLE, ~)
  190. return true;
  191. }
  192. #if N != 0
  193. template<class Sig BOOST_PP_ENUM_TRAILING_PARAMS(N, class U)>
  194. struct BOOST_PP_CAT(do_extract_concept, N);
  195. template<
  196. class R
  197. BOOST_PP_ENUM_TRAILING_PARAMS(N, class T)
  198. BOOST_PP_ENUM_TRAILING_PARAMS(N, class U)
  199. >
  200. struct BOOST_PP_CAT(do_extract_concept, N)<
  201. R(BOOST_PP_ENUM_PARAMS(N, T))
  202. BOOST_PP_ENUM_TRAILING_PARAMS(N, U)
  203. >
  204. : ::boost::type_erasure::detail::BOOST_PP_CAT(extract_concept, N)<
  205. BOOST_PP_ENUM_PARAMS(N, T)
  206. BOOST_PP_ENUM_TRAILING_PARAMS(N, U)>
  207. {};
  208. #endif
  209. }
  210. #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
  211. #define RREF &
  212. #else
  213. #define RREF &&
  214. #endif
  215. template<
  216. class Concept,
  217. class Op
  218. BOOST_PP_ENUM_TRAILING_PARAMS(N, class U)
  219. >
  220. bool check_match(
  221. const ::boost::type_erasure::binding<Concept>& table,
  222. const Op&
  223. BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, U, RREF arg))
  224. {
  225. return ::boost::type_erasure::detail::BOOST_PP_CAT(check_table, N)(
  226. &table,
  227. (typename ::boost::type_erasure::detail::get_signature<Op>::type*)0
  228. BOOST_PP_ENUM_TRAILING_PARAMS(N, arg));
  229. }
  230. #if N != 0
  231. template<
  232. class Op
  233. BOOST_PP_ENUM_TRAILING_PARAMS(N, class U)
  234. >
  235. bool check_match(
  236. const Op&
  237. BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, U, RREF arg))
  238. {
  239. const ::boost::type_erasure::binding<
  240. typename ::boost::type_erasure::detail::BOOST_PP_CAT(do_extract_concept, N)<
  241. typename ::boost::type_erasure::detail::get_signature<Op>::type,
  242. BOOST_PP_ENUM_PARAMS(N, U)>::type>* p = 0;
  243. return ::boost::type_erasure::detail::BOOST_PP_CAT(check_table, N)(
  244. p,
  245. (typename ::boost::type_erasure::detail::get_signature<Op>::type*)0
  246. BOOST_PP_ENUM_TRAILING_PARAMS(N, arg));
  247. }
  248. #undef RREF
  249. #undef BOOST_TYPE_ERASURE_CHECK_TABLE
  250. #undef N
  251. #endif
  252. #endif