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

source code of boost/libs/type_erasure/include/boost/type_erasure/require_match.hpp