]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /////////////////////////////////////////////////////////////////////////////// |
2 | /// \file repeat.hpp | |
3 | /// Contains macros to ease the generation of repetitious code constructs | |
4 | // | |
5 | // Copyright 2008 Eric Niebler. Distributed under the Boost | |
6 | // Software License, Version 1.0. (See accompanying file | |
7 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
8 | ||
9 | #ifndef BOOST_PROTO_REPEAT_HPP_EAN_11_24_2008 | |
10 | #define BOOST_PROTO_REPEAT_HPP_EAN_11_24_2008 | |
11 | ||
12 | #include <boost/preprocessor/cat.hpp> | |
13 | #include <boost/preprocessor/facilities/intercept.hpp> | |
14 | #include <boost/preprocessor/repetition/enum.hpp> | |
15 | #include <boost/preprocessor/repetition/enum_params.hpp> | |
16 | #include <boost/preprocessor/repetition/enum_binary_params.hpp> | |
17 | #include <boost/preprocessor/iteration/local.hpp> | |
18 | #include <boost/preprocessor/tuple/elem.hpp> | |
19 | #include <boost/proto/proto_fwd.hpp> // for BOOST_PROTO_MAX_ARITY | |
20 | ||
21 | //////////////////////////////////////////// | |
22 | /// INTERNAL ONLY | |
23 | #define BOOST_PROTO_ref_a_aux(Z, N, DATA)\ | |
24 | boost::ref(BOOST_PP_CAT(proto_a, N)) | |
25 | ||
26 | /// \brief Generates a sequence like <tt>typename A0, typename A1, ...</tt> | |
27 | /// | |
28 | #define BOOST_PROTO_typename_A(N)\ | |
29 | BOOST_PP_ENUM_PARAMS(N, typename proto_A) | |
30 | ||
31 | /// \brief Generates a sequence like <tt>A0 const &, A1 const &, ...</tt> | |
32 | /// | |
33 | #define BOOST_PROTO_A_const_ref(N)\ | |
34 | BOOST_PP_ENUM_BINARY_PARAMS(N, proto_A, const & BOOST_PP_INTERCEPT) | |
35 | ||
36 | /// \brief Generates a sequence like <tt>A0 &, A1 &, ...</tt> | |
37 | /// | |
38 | #define BOOST_PROTO_A_ref(N)\ | |
39 | BOOST_PP_ENUM_BINARY_PARAMS(N, proto_A, & BOOST_PP_INTERCEPT) | |
40 | ||
41 | /// \brief Generates a sequence like <tt>A0, A1, ...</tt> | |
42 | /// | |
43 | #define BOOST_PROTO_A(N)\ | |
44 | BOOST_PP_ENUM_PARAMS(N, proto_A) | |
45 | ||
46 | /// \brief Generates a sequence like <tt>A0 const, A1 const, ...</tt> | |
47 | /// | |
48 | #define BOOST_PROTO_A_const(N)\ | |
49 | BOOST_PP_ENUM_PARAMS(N, const proto_A) | |
50 | ||
51 | /// \brief Generates a sequence like <tt>A0 const &a0, A1 const &a0, ...</tt> | |
52 | /// | |
53 | #define BOOST_PROTO_A_const_ref_a(N)\ | |
54 | BOOST_PP_ENUM_BINARY_PARAMS(N, proto_A, const &proto_a) | |
55 | ||
56 | /// \brief Generates a sequence like <tt>A0 &a0, A1 &a0, ...</tt> | |
57 | /// | |
58 | #define BOOST_PROTO_A_ref_a(N)\ | |
59 | BOOST_PP_ENUM_BINARY_PARAMS(N, proto_A, &proto_a) | |
60 | ||
61 | /// \brief Generates a sequence like <tt>boost::ref(a0), boost::ref(a1), ...</tt> | |
62 | /// | |
63 | #define BOOST_PROTO_ref_a(N)\ | |
64 | BOOST_PP_ENUM(N, BOOST_PROTO_ref_a_aux, ~) | |
65 | ||
66 | /// \brief Generates a sequence like <tt>a0, a1, ...</tt> | |
67 | /// | |
68 | #define BOOST_PROTO_a(N)\ | |
69 | BOOST_PP_ENUM_PARAMS(N, proto_a) | |
70 | ||
71 | //////////////////////////////////////////// | |
72 | /// INTERNAL ONLY | |
73 | #define BOOST_PROTO_invoke(Z, N, DATA)\ | |
74 | BOOST_PP_TUPLE_ELEM(5,0,DATA)(N, BOOST_PP_TUPLE_ELEM(5,1,DATA), BOOST_PP_TUPLE_ELEM(5,2,DATA), BOOST_PP_TUPLE_ELEM(5,3,DATA), BOOST_PP_TUPLE_ELEM(5,4,DATA)) | |
75 | ||
76 | /// \brief Repeatedly invoke the specified macro. | |
77 | /// | |
78 | /// BOOST_PROTO_REPEAT_FROM_TO_EX() is used generate the kind of repetitive code that is typical | |
79 | /// of EDSLs built with Proto. BOOST_PROTO_REPEAT_FROM_TO_EX(FROM, TO, MACRO, typename_A, A, A_a, a) is equivalent to: | |
80 | /// | |
81 | /// \code | |
82 | /// MACRO(FROM, typename_A, A, A_a, a) | |
83 | /// MACRO(FROM+1, typename_A, A, A_a, a) | |
84 | /// ... | |
85 | /// MACRO(TO-1, typename_A, A, A_a, a) | |
86 | /// \endcode | |
87 | #define BOOST_PROTO_REPEAT_FROM_TO_EX(FROM, TO, MACRO, typename_A, A, A_a, a)\ | |
88 | BOOST_PP_REPEAT_FROM_TO(FROM, TO, BOOST_PROTO_invoke, (MACRO, typename_A, A, A_a, a)) | |
89 | ||
90 | /// \brief Repeatedly invoke the specified macro. | |
91 | /// | |
92 | /// BOOST_PROTO_REPEAT_FROM_TO() is used generate the kind of repetitive code that is typical | |
93 | /// of EDSLs built with Proto. BOOST_PROTO_REPEAT_FROM_TO(FROM, TO, MACRO) is equivalent to: | |
94 | /// | |
95 | /// \code | |
96 | /// MACRO(FROM, BOOST_PROTO_typename_A, BOOST_PROTO_A_const_ref, BOOST_PROTO_A_const_ref_a, BOOST_PROTO_ref_a) | |
97 | /// MACRO(FROM+1, BOOST_PROTO_typename_A, BOOST_PROTO_A_const_ref, BOOST_PROTO_A_const_ref_a, BOOST_PROTO_ref_a) | |
98 | /// ... | |
99 | /// MACRO(TO-1, BOOST_PROTO_typename_A, BOOST_PROTO_A_const_ref, BOOST_PROTO_A_const_ref_a, BOOST_PROTO_ref_a) | |
100 | /// \endcode | |
101 | /// | |
102 | /// Example: | |
103 | /// | |
104 | /** \code | |
105 | ||
106 | // Generate BOOST_PROTO_MAX_ARITY-1 overloads of the | |
107 | // following construct() function template. | |
108 | #define M0(N, typename_A, A_const_ref, A_const_ref_a, ref_a) \ | |
109 | template<typename T, typename_A(N)> \ | |
110 | typename proto::result_of::make_expr< \ | |
111 | proto::tag::function \ | |
112 | , construct_helper<T> \ | |
113 | , A_const_ref(N) \ | |
114 | >::type const \ | |
115 | construct(A_const_ref_a(N)) \ | |
116 | { \ | |
117 | return proto::make_expr< \ | |
118 | proto::tag::function \ | |
119 | >( \ | |
120 | construct_helper<T>() \ | |
121 | , ref_a(N) \ | |
122 | ); \ | |
123 | } | |
124 | BOOST_PROTO_REPEAT_FROM_TO(1, BOOST_PROTO_MAX_ARITY, M0) | |
125 | #undef M0 | |
126 | ||
127 | \endcode | |
128 | **/ | |
129 | /// The above invocation of BOOST_PROTO_REPEAT_FROM_TO() will generate | |
130 | /// the following code: | |
131 | /// | |
132 | /// \code | |
133 | /// template<typename T, typename A0> | |
134 | /// typename proto::result_of::make_expr< | |
135 | /// proto::tag::function | |
136 | /// , construct_helper<T> | |
137 | /// , A0 const & | |
138 | /// >::type const | |
139 | /// construct(A0 const & a0) | |
140 | /// { | |
141 | /// return proto::make_expr< | |
142 | /// proto::tag::function | |
143 | /// >( | |
144 | /// construct_helper<T>() | |
145 | /// , boost::ref(a0) | |
146 | /// ); | |
147 | /// } | |
148 | /// | |
149 | /// template<typename T, typename A0, typename A1> | |
150 | /// typename proto::result_of::make_expr< | |
151 | /// proto::tag::function | |
152 | /// , construct_helper<T> | |
153 | /// , A0 const & | |
154 | /// , A1 const & | |
155 | /// >::type const | |
156 | /// construct(A0 const & a0, A1 const & a1) | |
157 | /// { | |
158 | /// return proto::make_expr< | |
159 | /// proto::tag::function | |
160 | /// >( | |
161 | /// construct_helper<T>() | |
162 | /// , boost::ref(a0) | |
163 | /// , boost::ref(a1) | |
164 | /// ); | |
165 | /// } | |
166 | /// | |
167 | /// // ... and so on, up to BOOST_PROTO_MAX_ARITY-1 arguments ... | |
168 | /// \endcode | |
169 | #define BOOST_PROTO_REPEAT_FROM_TO(FROM, TO, MACRO)\ | |
170 | BOOST_PROTO_REPEAT_FROM_TO_EX(FROM, TO, MACRO, BOOST_PROTO_typename_A, BOOST_PROTO_A_const_ref, BOOST_PROTO_A_const_ref_a, BOOST_PROTO_ref_a) | |
171 | ||
172 | /// \brief Repeatedly invoke the specified macro. | |
173 | /// | |
174 | /// BOOST_PROTO_REPEAT_EX() is used generate the kind of repetitive code that is typical | |
175 | /// of EDSLs built with Proto. BOOST_PROTO_REPEAT_EX(MACRO, typename_A, A, A_a, a) is equivalent to: | |
176 | /// | |
177 | /// \code | |
178 | /// MACRO(1, typename_A, A, A_a, a) | |
179 | /// MACRO(2, typename_A, A, A_a, a) | |
180 | /// ... | |
181 | /// MACRO(BOOST_PROTO_MAX_ARITY, typename_A, A, A_a, a) | |
182 | /// \endcode | |
183 | #define BOOST_PROTO_REPEAT_EX(MACRO, typename_A, A, A_a, a)\ | |
184 | BOOST_PROTO_REPEAT_FROM_TO_EX(1, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), MACRO, BOOST_PROTO_typename_A, BOOST_PROTO_A_const_ref, BOOST_PROTO_A_const_ref_a, BOOST_PROTO_ref_a) | |
185 | ||
186 | /// \brief Repeatedly invoke the specified macro. | |
187 | /// | |
188 | /// BOOST_PROTO_REPEAT() is used generate the kind of repetitive code that is typical | |
189 | /// of EDSLs built with Proto. BOOST_PROTO_REPEAT(MACRO) is equivalent to: | |
190 | /// | |
191 | /// \code | |
192 | /// MACRO(1, BOOST_PROTO_typename_A, BOOST_PROTO_A_const_ref, BOOST_PROTO_A_const_ref_a, BOOST_PROTO_ref_a) | |
193 | /// MACRO(2, BOOST_PROTO_typename_A, BOOST_PROTO_A_const_ref, BOOST_PROTO_A_const_ref_a, BOOST_PROTO_ref_a) | |
194 | /// ... | |
195 | /// MACRO(BOOST_PROTO_MAX_ARITY, BOOST_PROTO_typename_A, BOOST_PROTO_A_const_ref, BOOST_PROTO_A_const_ref_a, BOOST_PROTO_ref_a) | |
196 | /// \endcode | |
197 | #define BOOST_PROTO_REPEAT(MACRO)\ | |
198 | BOOST_PROTO_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), MACRO) | |
199 | ||
200 | /// \brief Repeatedly invoke the specified macro. | |
201 | /// | |
202 | /// BOOST_PROTO_LOCAL_ITERATE() is used generate the kind of repetitive code that is typical | |
203 | /// of EDSLs built with Proto. This macro causes the user-defined macro BOOST_PROTO_LOCAL_MACRO to | |
204 | /// be expanded with values in the range specified by BOOST_PROTO_LOCAL_LIMITS. | |
205 | /// | |
206 | /// Usage: | |
207 | /// | |
208 | /// \code | |
209 | /// #include BOOST_PROTO_LOCAL_ITERATE() | |
210 | /// \endcode | |
211 | /// | |
212 | /// Example: | |
213 | /// | |
214 | /** \code | |
215 | ||
216 | // Generate BOOST_PROTO_MAX_ARITY-1 overloads of the | |
217 | // following construct() function template. | |
218 | #define BOOST_PROTO_LOCAL_MACRO(N, typename_A, A_const_ref, \ | |
219 | A_const_ref_a, ref_a) \ | |
220 | template<typename T, typename_A(N)> \ | |
221 | typename proto::result_of::make_expr< \ | |
222 | proto::tag::function \ | |
223 | , construct_helper<T> \ | |
224 | , A_const_ref(N) \ | |
225 | >::type const \ | |
226 | construct(A_const_ref_a(N)) \ | |
227 | { \ | |
228 | return proto::make_expr< \ | |
229 | proto::tag::function \ | |
230 | >( \ | |
231 | construct_helper<T>() \ | |
232 | , ref_a(N) \ | |
233 | ); \ | |
234 | } | |
235 | #define BOOST_PROTO_LOCAL_LIMITS (1, BOOST_PP_DEC(BOOST_PROTO_MAX_ARITY)) | |
236 | #include BOOST_PROTO_LOCAL_ITERATE() | |
237 | ||
238 | \endcode | |
239 | **/ | |
240 | /// The above inclusion of BOOST_PROTO_LOCAL_ITERATE() will generate | |
241 | /// the following code: | |
242 | /// | |
243 | /// \code | |
244 | /// template<typename T, typename A0> | |
245 | /// typename proto::result_of::make_expr< | |
246 | /// proto::tag::function | |
247 | /// , construct_helper<T> | |
248 | /// , A0 const & | |
249 | /// >::type const | |
250 | /// construct(A0 const & a0) | |
251 | /// { | |
252 | /// return proto::make_expr< | |
253 | /// proto::tag::function | |
254 | /// >( | |
255 | /// construct_helper<T>() | |
256 | /// , boost::ref(a0) | |
257 | /// ); | |
258 | /// } | |
259 | /// | |
260 | /// template<typename T, typename A0, typename A1> | |
261 | /// typename proto::result_of::make_expr< | |
262 | /// proto::tag::function | |
263 | /// , construct_helper<T> | |
264 | /// , A0 const & | |
265 | /// , A1 const & | |
266 | /// >::type const | |
267 | /// construct(A0 const & a0, A1 const & a1) | |
268 | /// { | |
269 | /// return proto::make_expr< | |
270 | /// proto::tag::function | |
271 | /// >( | |
272 | /// construct_helper<T>() | |
273 | /// , boost::ref(a0) | |
274 | /// , boost::ref(a1) | |
275 | /// ); | |
276 | /// } | |
277 | /// | |
278 | /// // ... and so on, up to BOOST_PROTO_MAX_ARITY-1 arguments ... | |
279 | /// \endcode | |
280 | /// | |
281 | /// If BOOST_PROTO_LOCAL_LIMITS is not defined by the user, it defaults | |
282 | /// to (1, BOOST_PROTO_MAX_ARITY) | |
283 | /// | |
284 | /// At each iteration, BOOST_PROTO_LOCAL_MACRO is invoked with the current | |
285 | /// iteration number and the following 4 macro parameters: | |
286 | /// | |
287 | /// \li BOOST_PROTO_LOCAL_typename_A | |
288 | /// \li BOOST_PROTO_LOCAL_A | |
289 | /// \li BOOST_PROTO_LOCAL_A_a | |
290 | /// \li BOOST_PROTO_LOCAL_a | |
291 | /// | |
292 | /// If these macros are not defined by the user, they default respectively to: | |
293 | /// | |
294 | /// \li BOOST_PROTO_typename_A | |
295 | /// \li BOOST_PROTO_A_const_ref | |
296 | /// \li BOOST_PROTO_A_const_ref_a | |
297 | /// \li BOOST_PROTO_ref_a | |
298 | /// | |
299 | /// After including BOOST_PROTO_LOCAL_ITERATE(), the following macros are | |
300 | /// automatically undefined: | |
301 | /// | |
302 | /// \li BOOST_PROTO_LOCAL_MACRO | |
303 | /// \li BOOST_PROTO_LOCAL_LIMITS | |
304 | /// \li BOOST_PROTO_LOCAL_typename_A | |
305 | /// \li BOOST_PROTO_LOCAL_A | |
306 | /// \li BOOST_PROTO_LOCAL_A_a | |
307 | /// \li BOOST_PROTO_LOCAL_a | |
308 | #define BOOST_PROTO_LOCAL_ITERATE() <boost/proto/detail/local.hpp> | |
309 | ||
310 | #endif |