1 /*============================================================================= 2 Copyright (c) 2007-2008 Tobias Schwinger 3 4 Use modification and distribution are subject to the Boost Software 5 License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 6 http://www.boost.org/LICENSE_1_0.txt). 7 ==============================================================================*/ 8 9 #ifndef BOOST_FUNCTIONAL_FORWARD_ADAPTER_HPP_INCLUDED 10 # ifndef BOOST_PP_IS_ITERATING 11 12 # include <boost/config.hpp> 13 # include <boost/detail/workaround.hpp> 14 15 # include <boost/preprocessor/iteration/iterate.hpp> 16 # include <boost/preprocessor/repetition/enum_params.hpp> 17 # include <boost/preprocessor/repetition/enum_binary_params.hpp> 18 # include <boost/preprocessor/facilities/intercept.hpp> 19 # include <boost/preprocessor/arithmetic/dec.hpp> 20 21 # include <boost/utility/result_of.hpp> 22 23 # ifndef BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY 24 # define BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY 6 25 # elif BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY < 3 26 # undef BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY 27 # define BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY 3 28 # endif 29 30 31 namespace boost 32 { 33 template< typename Function, int Arity_Or_MinArity = -1, int MaxArity = -1 > 34 class forward_adapter; 35 36 //----- ---- --- -- - - - - 37 38 namespace detail 39 { 40 template< class MostDerived, typename Function, typename FunctionConst, 41 int Arity, int MinArity > 42 struct forward_adapter_impl; 43 44 struct forward_adapter_result 45 { 46 template< typename Sig > struct apply; 47 48 // Utility metafunction for qualification adjustment on arguments 49 template< typename T > struct q { typedef T const t; }; 50 template< typename T > struct q<T const> { typedef T const t; }; 51 template< typename T > struct q<T &> { typedef T t; }; 52 53 // Utility metafunction to choose target function qualification 54 template< typename T > struct c 55 { typedef typename T::target_function_t t; }; 56 template< typename T > struct c<T& > 57 { typedef typename T::target_function_t t; }; 58 template< typename T > struct c<T const > 59 { typedef typename T::target_function_const_t t; }; 60 template< typename T > struct c<T const&> 61 { typedef typename T::target_function_const_t t; }; 62 }; 63 } 64 65 # define BOOST_TMP_MACRO(f,fn,fc) \ 66 boost::detail::forward_adapter_impl< \ 67 forward_adapter<f,Arity_Or_MinArity,MaxArity>, fn, fc, \ 68 (MaxArity!=-1? MaxArity :Arity_Or_MinArity!=-1? Arity_Or_MinArity \ 69 :BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY), \ 70 (Arity_Or_MinArity!=-1? Arity_Or_MinArity : 0) > 71 72 template< typename Function, int Arity_Or_MinArity, int MaxArity > 73 class forward_adapter 74 : public BOOST_TMP_MACRO(Function,Function,Function const) 75 , private Function 76 { 77 public: forward_adapter(Function const & f=Function ())78 forward_adapter(Function const& f = Function()) 79 : Function(f) 80 { } 81 82 typedef Function target_function_t; 83 typedef Function const target_function_const_t; 84 target_function()85 Function & target_function() { return *this; } target_function() const86 Function const & target_function() const { return *this; } 87 88 template< typename Sig > struct result 89 : detail::forward_adapter_result::template apply<Sig> 90 { }; 91 92 using BOOST_TMP_MACRO(Function,Function, Function const)::operator(); 93 }; 94 template< typename Function, int Arity_Or_MinArity, int MaxArity > 95 class forward_adapter< Function const, Arity_Or_MinArity, MaxArity > 96 : public BOOST_TMP_MACRO(Function const, Function const, Function const) 97 , private Function 98 { 99 public: forward_adapter(Function const & f=Function ())100 forward_adapter(Function const& f = Function()) 101 : Function(f) 102 { } 103 104 typedef Function const target_function_t; 105 typedef Function const target_function_const_t; 106 target_function() const107 Function const & target_function() const { return *this; } 108 109 template< typename Sig > struct result 110 : detail::forward_adapter_result::template apply<Sig> 111 { }; 112 113 using BOOST_TMP_MACRO(Function const,Function const, Function const) 114 ::operator(); 115 }; 116 template< typename Function, int Arity_Or_MinArity, int MaxArity > 117 class forward_adapter< Function &, Arity_Or_MinArity, MaxArity > 118 : public BOOST_TMP_MACRO(Function&, Function, Function) 119 { 120 Function& ref_function; 121 public: forward_adapter(Function & f)122 forward_adapter(Function& f) 123 : ref_function(f) 124 { } 125 126 typedef Function target_function_t; 127 typedef Function target_function_const_t; 128 target_function() const129 Function & target_function() const { return this->ref_function; } 130 131 template< typename Sig > struct result 132 : detail::forward_adapter_result::template apply<Sig> 133 { }; 134 135 using BOOST_TMP_MACRO(Function&, Function, Function)::operator(); 136 }; 137 138 #undef BOOST_TMP_MACRO 139 140 namespace detail 141 { 142 template< class Self > 143 struct forward_adapter_result::apply< Self() > 144 : boost::result_of< BOOST_DEDUCED_TYPENAME c<Self>::t() > 145 { }; 146 147 template< class MD, class F, class FC > 148 struct forward_adapter_impl<MD,F,FC,0,0> 149 { 150 inline typename boost::result_of< FC() >::type operator ()boost::detail::forward_adapter_impl151 operator()() const 152 { 153 return static_cast<MD const*>(this)->target_function()(); 154 } 155 156 inline typename boost::result_of< F() >::type operator ()boost::detail::forward_adapter_impl157 operator()() 158 { 159 return static_cast<MD*>(this)->target_function()(); 160 } 161 162 // closing brace gets generated by preprocessing code, below 163 164 # define BOOST_TMP_MACRO(tpl_params,arg_types,params,args) \ 165 template< tpl_params > \ 166 inline typename boost::result_of< FC(arg_types) >::type \ 167 operator()(params) const \ 168 { \ 169 return static_cast<MD const*>(this)->target_function()(args); \ 170 } \ 171 template< tpl_params > \ 172 inline typename boost::result_of< F(arg_types)>::type \ 173 operator()(params) \ 174 { \ 175 return static_cast<MD*>(this)->target_function()(args); \ 176 } 177 178 # // This is the total number of iterations we need 179 # define count ((1 << BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY+1)-2) 180 181 # // Chain file iteration to virtually one loop 182 # if BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY <= 7 183 # define limit1 count 184 # define limit2 0 185 # define limit3 0 186 # else 187 # if BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY <= 15 188 # define limit1 (count >> 8) 189 # define limit2 255 190 # define limit3 0 191 # else 192 # define limit1 (count >> 16) 193 # define limit2 255 194 # define limit3 255 195 # endif 196 # endif 197 198 # define N 0 199 200 # define BOOST_PP_FILENAME_1 <boost/functional/forward_adapter.hpp> 201 # define BOOST_PP_ITERATION_LIMITS (0,limit1) 202 # include BOOST_PP_ITERATE() 203 204 # undef N 205 # undef limit3 206 # undef limit2 207 # undef limit1 208 # undef count 209 # undef BOOST_TMP_MACRO 210 211 }; 212 213 } // namespace detail 214 215 template<class F, int A0, int A1> 216 struct result_of<boost::forward_adapter<F,A0,A1> const ()> 217 : boost::detail::forward_adapter_result::template apply< 218 boost::forward_adapter<F,A0,A1> const () > 219 { }; 220 template<class F, int A0, int A1> 221 struct result_of<boost::forward_adapter<F,A0,A1>()> 222 : boost::detail::forward_adapter_result::template apply< 223 boost::forward_adapter<F,A0,A1>() > 224 { }; 225 template<class F, int A0, int A1> 226 struct result_of<boost::forward_adapter<F,A0,A1> const& ()> 227 : boost::detail::forward_adapter_result::template apply< 228 boost::forward_adapter<F,A0,A1> const () > 229 { }; 230 template<class F, int A0, int A1> 231 struct result_of<boost::forward_adapter<F,A0,A1>& ()> 232 : boost::detail::forward_adapter_result::template apply< 233 boost::forward_adapter<F,A0,A1>() > 234 { }; 235 } 236 237 # define BOOST_FUNCTIONAL_FORWARD_ADAPTER_HPP_INCLUDED 238 239 # elif BOOST_PP_ITERATION_DEPTH() == 1 && limit2 240 # define BOOST_PP_FILENAME_2 <boost/functional/forward_adapter.hpp> 241 # define BOOST_PP_ITERATION_LIMITS (0,limit2) 242 # include BOOST_PP_ITERATE() 243 # elif BOOST_PP_ITERATION_DEPTH() == 2 && limit3 244 # define BOOST_PP_FILENAME_3 <boost/functional/forward_adapter.hpp> 245 # define BOOST_PP_ITERATION_LIMITS (0,limit3) 246 # include BOOST_PP_ITERATE() 247 248 # else 249 250 # // I is the loop counter 251 # if limit2 && limit3 252 # define I (BOOST_PP_ITERATION_1 << 16 | BOOST_PP_ITERATION_2 << 8 | \ 253 BOOST_PP_ITERATION_3) 254 # elif limit2 255 # define I (BOOST_PP_ITERATION_1 << 8 | BOOST_PP_ITERATION_2) 256 # else 257 # define I BOOST_PP_ITERATION_1 258 # endif 259 260 # if I < count 261 262 # // Done for this arity? Increment N 263 # if (I+2 >> N+1) 264 # if N == 0 265 # undef N 266 # define N 1 267 # elif N == 1 268 # undef N 269 # define N 2 270 # elif N == 2 271 # undef N 272 # define N 3 273 # elif N == 3 274 # undef N 275 # define N 4 276 # elif N == 4 277 # undef N 278 # define N 5 279 # elif N == 5 280 # undef N 281 # define N 6 282 # elif N == 6 283 # undef N 284 # define N 7 285 # elif N == 7 286 # undef N 287 # define N 8 288 # elif N == 8 289 # undef N 290 # define N 9 291 # elif N == 9 292 # undef N 293 # define N 10 294 # elif N == 10 295 # undef N 296 # define N 11 297 # elif N == 11 298 # undef N 299 # define N 12 300 # elif N == 12 301 # undef N 302 # define N 13 303 # elif N == 13 304 # undef N 305 # define N 14 306 # elif N == 14 307 # undef N 308 # define N 15 309 # elif N == 15 310 # undef N 311 # define N 16 312 # endif 313 314 }; 315 316 template< class Self, BOOST_PP_ENUM_PARAMS(N,typename T) > 317 struct forward_adapter_result::apply< Self(BOOST_PP_ENUM_PARAMS(N,T)) > 318 : boost::result_of< 319 BOOST_DEDUCED_TYPENAME c<Self>::t(BOOST_PP_ENUM_BINARY_PARAMS(N, 320 typename q<T,>::t& BOOST_PP_INTERCEPT)) > 321 { }; 322 323 template< class MD, class F, class FC > 324 struct forward_adapter_impl<MD,F,FC,BOOST_PP_DEC(N),N> 325 { 326 template< BOOST_PP_ENUM_PARAMS(N,typename T) > 327 inline typename boost::result_of< F( 328 BOOST_PP_ENUM_BINARY_PARAMS(N,T,& BOOST_PP_INTERCEPT)) >::type 329 operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,& BOOST_PP_INTERCEPT)); 330 }; 331 332 template< class MD, class F, class FC, int MinArity > 333 struct forward_adapter_impl<MD,F,FC,N,MinArity> 334 : forward_adapter_impl<MD,F,FC,BOOST_PP_DEC(N),MinArity> 335 { 336 using forward_adapter_impl<MD,F,FC,BOOST_PP_DEC(N),MinArity>::operator(); 337 338 # endif 339 340 # // Zero based count for each arity would be I-(1<<N)+2, but we don't 341 # // need it, unless we need a nicer order. 342 343 # // Macros for the parameter's type modifiers. 344 # if I & 0x000001 345 # define PT0 T0 & 346 # else 347 # define PT0 T0 const & 348 # endif 349 # if I & 0x000002 350 # define PT1 T1 & 351 # else 352 # define PT1 T1 const & 353 # endif 354 # if I & 0x000004 355 # define PT2 T2 & 356 # else 357 # define PT2 T2 const & 358 # endif 359 # if I & 0x000008 360 # define PT3 T3 & 361 # else 362 # define PT3 T3 const & 363 # endif 364 # if I & 0x000010 365 # define PT4 T4 & 366 # else 367 # define PT4 T4 const & 368 # endif 369 # if I & 0x000020 370 # define PT5 T5 & 371 # else 372 # define PT5 T5 const & 373 # endif 374 # if I & 0x000040 375 # define PT6 T6 & 376 # else 377 # define PT6 T6 const & 378 # endif 379 # if I & 0x000080 380 # define PT7 T7 & 381 # else 382 # define PT7 T7 const & 383 # endif 384 # if I & 0x000100 385 # define PT8 T8 & 386 # else 387 # define PT8 T8 const & 388 # endif 389 # if I & 0x000200 390 # define PT9 T9 & 391 # else 392 # define PT9 T9 const & 393 # endif 394 # if I & 0x000400 395 # define PT10 T10 & 396 # else 397 # define PT10 T10 const & 398 # endif 399 # if I & 0x000800 400 # define PT11 T11 & 401 # else 402 # define PT11 T11 const & 403 # endif 404 # if I & 0x001000 405 # define PT12 T12 & 406 # else 407 # define PT12 T12 const & 408 # endif 409 # if I & 0x002000 410 # define PT13 T13 & 411 # else 412 # define PT13 T13 const & 413 # endif 414 # if I & 0x004000 415 # define PT14 T14 & 416 # else 417 # define PT14 T14 const & 418 # endif 419 # if I & 0x008000 420 # define PT15 T15 & 421 # else 422 # define PT15 T15 const & 423 # endif 424 425 # if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1400)) 426 template< BOOST_PP_ENUM_PARAMS(N,typename T) > 427 inline typename boost::result_of< FC(BOOST_PP_ENUM_PARAMS(N,PT)) 428 >::type 429 operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,PT,a)) const 430 { 431 return static_cast<MD const* const>(this) 432 ->target_function()(BOOST_PP_ENUM_PARAMS(N,a)); 433 } 434 template< BOOST_PP_ENUM_PARAMS(N,typename T) > 435 inline typename boost::result_of< F(BOOST_PP_ENUM_PARAMS(N,PT)) 436 >::type 437 operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,PT,a)) 438 { 439 return static_cast<MD* const>(this) 440 ->target_function()(BOOST_PP_ENUM_PARAMS(N,a)); 441 } 442 # else 443 BOOST_TMP_MACRO(BOOST_PP_ENUM_PARAMS(N,typename T), 444 BOOST_PP_ENUM_PARAMS(N,PT), BOOST_PP_ENUM_BINARY_PARAMS(N,PT,a), 445 BOOST_PP_ENUM_PARAMS(N,a) ) 446 // ...generates uglier code but is faster - it caches ENUM_* 447 # endif 448 449 # undef PT0 450 # undef PT1 451 # undef PT2 452 # undef PT3 453 # undef PT4 454 # undef PT5 455 # undef PT6 456 # undef PT7 457 # undef PT8 458 # undef PT9 459 # undef PT10 460 # undef PT11 461 # undef PT12 462 # undef PT13 463 # undef PT14 464 # undef PT15 465 466 # endif // I < count 467 468 # undef I 469 # endif // defined(BOOST_PP_IS_ITERATING) 470 471 #endif // include guard 472 473