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 311