require_match.hpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. // Boost.TypeErasure library
  2. //
  3. // Copyright 2011-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. #if !defined(BOOST_PP_IS_ITERATING)
  11. #ifndef BOOST_TYPE_ERASURE_REQUIRE_MATCH_HPP_INCLUDED
  12. #define BOOST_TYPE_ERASURE_REQUIRE_MATCH_HPP_INCLUDED
  13. #include <boost/throw_exception.hpp>
  14. #include <boost/mpl/bool.hpp>
  15. #include <boost/mpl/and.hpp>
  16. #include <boost/type_traits/is_same.hpp>
  17. #include <boost/preprocessor/cat.hpp>
  18. #include <boost/preprocessor/facilities/intercept.hpp>
  19. #include <boost/preprocessor/iteration/iterate.hpp>
  20. #include <boost/preprocessor/repetition/repeat.hpp>
  21. #include <boost/preprocessor/repetition/enum_params.hpp>
  22. #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
  23. #include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
  24. #include <boost/type_erasure/detail/extract_concept.hpp>
  25. #include <boost/type_erasure/relaxed.hpp>
  26. #include <boost/type_erasure/check_match.hpp>
  27. #include <boost/type_erasure/exception.hpp>
  28. namespace boost {
  29. namespace type_erasure {
  30. #ifndef BOOST_TYPE_ERASURE_DOXYGEN
  31. template<class Concept>
  32. class binding;
  33. #endif
  34. #ifdef BOOST_TYPE_ERASURE_DOXYGEN
  35. /**
  36. * Checks that the actual types stored in all the @ref any
  37. * arguments match the types specified by @c binding. If
  38. * they do not match then,
  39. * - If @ref relaxed is in @c Concept, throws @ref bad_function_call.
  40. * - Otherwise the behavior is undefined.
  41. *
  42. * If @c binding is not specified, it will be deduced from
  43. * the arguments.
  44. *
  45. * \post \call<code>(binding, f, args...)</code> is valid.
  46. */
  47. template<class Concept, class Op, class... U>
  48. void require_match(const binding<Concept>& binding_arg, const Op& f, U&&... args);
  49. /**
  50. * \overload
  51. */
  52. template<class Op, class... U>
  53. void require_match(const Op& f, U&&... args);
  54. #else
  55. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  56. namespace detail {
  57. template<class Concept, class Op, class... U>
  58. void require_match_impl(
  59. ::boost::mpl::true_,
  60. const ::boost::type_erasure::binding<Concept>& table,
  61. const Op& op,
  62. U&&... arg)
  63. {
  64. if(!::boost::type_erasure::check_match(table, op, std::forward<U>(arg)...)) {
  65. BOOST_THROW_EXCEPTION(::boost::type_erasure::bad_function_call());
  66. }
  67. }
  68. template<class Concept, class Op, class... U>
  69. void require_match_impl(
  70. ::boost::mpl::false_,
  71. const ::boost::type_erasure::binding<Concept>&,
  72. const Op&,
  73. U&&...)
  74. {}
  75. template<class Op, class... U>
  76. void require_match_impl(
  77. ::boost::mpl::true_,
  78. const Op& op,
  79. U&&... arg)
  80. {
  81. if(!::boost::type_erasure::check_match(op, ::std::forward<U>(arg)...)) {
  82. BOOST_THROW_EXCEPTION(::boost::type_erasure::bad_function_call());
  83. }
  84. }
  85. template<class Op, class... U>
  86. void require_match_impl(
  87. ::boost::mpl::false_,
  88. const Op&,
  89. U&&...)
  90. {}
  91. }
  92. template<class Concept, class Op, class... U>
  93. void require_match(
  94. const ::boost::type_erasure::binding<Concept>& table,
  95. const Op& op,
  96. U&&... arg)
  97. {
  98. ::boost::type_erasure::is_relaxed<Concept> cond;
  99. ::boost::type_erasure::detail::require_match_impl(cond, table, op, ::std::forward<U>(arg)...);
  100. }
  101. #ifndef BOOST_TYPE_ERASURE_USE_MP11
  102. template<class Op, class... U>
  103. void require_match(
  104. const Op& op,
  105. U&&... arg)
  106. {
  107. ::boost::type_erasure::is_relaxed<
  108. typename ::boost::type_erasure::detail::extract_concept<
  109. typename ::boost::type_erasure::detail::get_signature<Op>::type,
  110. U...>::type
  111. > cond;
  112. ::boost::type_erasure::detail::require_match_impl(cond, op, ::std::forward<U>(arg)...);
  113. }
  114. #else
  115. template<class Op, class... U>
  116. void require_match(
  117. const Op& op,
  118. U&&... arg)
  119. {
  120. ::boost::type_erasure::is_relaxed<
  121. ::boost::type_erasure::detail::extract_concept_t<
  122. ::boost::type_erasure::detail::get_args_t<
  123. typename ::boost::type_erasure::detail::get_signature<Op>::type
  124. >,
  125. ::boost::mp11::mp_list< ::boost::remove_reference_t<U>...> >
  126. > cond;
  127. ::boost::type_erasure::detail::require_match_impl(cond, op, ::std::forward<U>(arg)...);
  128. }
  129. #endif
  130. #else
  131. #define BOOST_PP_FILENAME_1 <boost/type_erasure/require_match.hpp>
  132. #define BOOST_PP_ITERATION_LIMITS (0, BOOST_TYPE_ERASURE_MAX_ARITY)
  133. #include BOOST_PP_ITERATE()
  134. #endif
  135. #endif
  136. }
  137. }
  138. #endif
  139. #else
  140. #define N BOOST_PP_ITERATION()
  141. #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
  142. #define RREF &
  143. #define BOOST_TYPE_ERASURE_FORWARD_ARGS(N, X, x) BOOST_PP_ENUM_TRAILING_PARAMS(N, x)
  144. #else
  145. #define RREF &&
  146. #define BOOST_TYPE_ERASURE_FORWARD_ARGS_I(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))
  147. #define BOOST_TYPE_ERASURE_FORWARD_ARGS(N, X, x) BOOST_PP_ENUM_TRAILING(N, BOOST_TYPE_ERASURE_FORWARD_ARGS_I, (X, x))
  148. #endif
  149. namespace detail {
  150. template<
  151. class Concept,
  152. class Op
  153. BOOST_PP_ENUM_TRAILING_PARAMS(N, class U)
  154. >
  155. void require_match_impl(
  156. ::boost::mpl::true_,
  157. const ::boost::type_erasure::binding<Concept>& table,
  158. const Op& op
  159. BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, U, RREF arg))
  160. {
  161. if(!::boost::type_erasure::check_match
  162. (table, op BOOST_TYPE_ERASURE_FORWARD_ARGS(N, U, arg))) {
  163. BOOST_THROW_EXCEPTION(::boost::type_erasure::bad_function_call());
  164. }
  165. }
  166. template<
  167. class Concept,
  168. class Op
  169. BOOST_PP_ENUM_TRAILING_PARAMS(N, class U)
  170. >
  171. void require_match_impl(
  172. ::boost::mpl::false_,
  173. const ::boost::type_erasure::binding<Concept>&,
  174. const Op&
  175. BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, U, RREF BOOST_PP_INTERCEPT))
  176. {}
  177. #if N != 0
  178. template<
  179. class Op
  180. BOOST_PP_ENUM_TRAILING_PARAMS(N, class U)
  181. >
  182. void require_match_impl(
  183. ::boost::mpl::true_,
  184. const Op& op
  185. BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, U, RREF arg))
  186. {
  187. if(!::boost::type_erasure::check_match
  188. (op BOOST_TYPE_ERASURE_FORWARD_ARGS(N, U, arg))) {
  189. BOOST_THROW_EXCEPTION(::boost::type_erasure::bad_function_call());
  190. }
  191. }
  192. template<
  193. class Op
  194. BOOST_PP_ENUM_TRAILING_PARAMS(N, class U)
  195. >
  196. void require_match_impl(
  197. ::boost::mpl::false_,
  198. const Op&
  199. BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, U, RREF BOOST_PP_INTERCEPT))
  200. {}
  201. #endif
  202. }
  203. template<
  204. class Concept,
  205. class Op
  206. BOOST_PP_ENUM_TRAILING_PARAMS(N, class U)
  207. >
  208. void require_match(
  209. const ::boost::type_erasure::binding<Concept>& table,
  210. const Op& op
  211. BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, U, RREF arg))
  212. {
  213. ::boost::type_erasure::is_relaxed<Concept> cond;
  214. ::boost::type_erasure::detail::require_match_impl
  215. (cond, table, op BOOST_TYPE_ERASURE_FORWARD_ARGS(N, U, arg));
  216. }
  217. #if N != 0
  218. template<
  219. class Op
  220. BOOST_PP_ENUM_TRAILING_PARAMS(N, class U)
  221. >
  222. void require_match(
  223. const Op& op
  224. BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, U, RREF arg))
  225. {
  226. ::boost::type_erasure::is_relaxed<
  227. typename ::boost::type_erasure::detail::BOOST_PP_CAT(do_extract_concept, N)<
  228. typename ::boost::type_erasure::detail::get_signature<Op>::type,
  229. BOOST_PP_ENUM_PARAMS(N, U)>::type
  230. > cond;
  231. ::boost::type_erasure::detail::require_match_impl
  232. (cond, op BOOST_TYPE_ERASURE_FORWARD_ARGS(N, U, arg));
  233. }
  234. #endif
  235. #undef RREF
  236. #undef BOOST_TYPE_ERASURE_FORWARD_ARGS
  237. #undef BOOST_TYPE_ERASURE_FORWARD_ARGS_I
  238. #undef N
  239. #endif