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/config/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 // WHen operator()() doesn't have any parameters, it can't 148 // be templatized and can't use SFINAE, so intead use class 149 // template parameter SFINAE to decide whether to instantiate it. 150 151 template <typename T, typename R = void> 152 struct forward_adapter_sfinae 153 { 154 typedef T type; 155 }; 156 157 // This is the fallback for when there isn't an operator()(), 158 // need to create an operator() that will never instantiate 159 // so that using parent::operator() will work okay. 160 template< class MD, class F, class FC, class Enable = void> 161 struct forward_adapter_impl_zero 162 { 163 template <typename T> struct never_instantiate {}; 164 template <typename T> operator ()boost::detail::forward_adapter_impl_zero165 typename never_instantiate<T>::type operator()(T) const {} 166 }; 167 168 template< class MD, class F, class FC> 169 struct forward_adapter_impl_zero<MD, F, FC, 170 typename forward_adapter_sfinae<typename boost::result_of< FC() >::type>::type> 171 { 172 inline typename boost::result_of< FC() >::type operator ()boost::detail::forward_adapter_impl_zero173 operator()() const 174 { 175 return static_cast<MD const*>(this)->target_function()(); 176 } 177 178 inline typename boost::result_of< F() >::type operator ()boost::detail::forward_adapter_impl_zero179 operator()() 180 { 181 return static_cast<MD*>(this)->target_function()(); 182 } 183 }; 184 185 template< class MD, class F, class FC > 186 struct forward_adapter_impl<MD,F,FC,0,0> 187 : forward_adapter_impl_zero<MD,F,FC> 188 { 189 using forward_adapter_impl_zero<MD,F,FC>::operator(); 190 191 // closing brace gets generated by preprocessing code, below 192 193 # define BOOST_TMP_MACRO(tpl_params,arg_types,params,args) \ 194 template< tpl_params > \ 195 inline typename boost::result_of< FC(arg_types) >::type \ 196 operator()(params) const \ 197 { \ 198 return static_cast<MD const*>(this)->target_function()(args); \ 199 } \ 200 template< tpl_params > \ 201 inline typename boost::result_of< F(arg_types)>::type \ 202 operator()(params) \ 203 { \ 204 return static_cast<MD*>(this)->target_function()(args); \ 205 } 206 207 # // This is the total number of iterations we need 208 # define count ((1 << BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY+1)-2) 209 210 # // Chain file iteration to virtually one loop 211 # if BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY <= 7 212 # define limit1 count 213 # define limit2 0 214 # define limit3 0 215 # else 216 # if BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY <= 15 217 # define limit1 (count >> 8) 218 # define limit2 255 219 # define limit3 0 220 # else 221 # define limit1 (count >> 16) 222 # define limit2 255 223 # define limit3 255 224 # endif 225 # endif 226 227 # define N 0 228 229 # define BOOST_PP_FILENAME_1 <boost/functional/forward_adapter.hpp> 230 # define BOOST_PP_ITERATION_LIMITS (0,limit1) 231 # include BOOST_PP_ITERATE() 232 233 # undef N 234 # undef limit3 235 # undef limit2 236 # undef limit1 237 # undef count 238 # undef BOOST_TMP_MACRO 239 240 }; 241 242 } // namespace detail 243 244 template<class F, int A0, int A1> 245 struct result_of<boost::forward_adapter<F,A0,A1> const ()> 246 : boost::detail::forward_adapter_result::template apply< 247 boost::forward_adapter<F,A0,A1> const () > 248 { }; 249 template<class F, int A0, int A1> 250 struct result_of<boost::forward_adapter<F,A0,A1>()> 251 : boost::detail::forward_adapter_result::template apply< 252 boost::forward_adapter<F,A0,A1>() > 253 { }; 254 template<class F, int A0, int A1> 255 struct result_of<boost::forward_adapter<F,A0,A1> const& ()> 256 : boost::detail::forward_adapter_result::template apply< 257 boost::forward_adapter<F,A0,A1> const () > 258 { }; 259 template<class F, int A0, int A1> 260 struct result_of<boost::forward_adapter<F,A0,A1>& ()> 261 : boost::detail::forward_adapter_result::template apply< 262 boost::forward_adapter<F,A0,A1>() > 263 { }; 264 } 265 266 # define BOOST_FUNCTIONAL_FORWARD_ADAPTER_HPP_INCLUDED 267 268 # elif BOOST_PP_ITERATION_DEPTH() == 1 && limit2 269 # define BOOST_PP_FILENAME_2 <boost/functional/forward_adapter.hpp> 270 # define BOOST_PP_ITERATION_LIMITS (0,limit2) 271 # include BOOST_PP_ITERATE() 272 # elif BOOST_PP_ITERATION_DEPTH() == 2 && limit3 273 # define BOOST_PP_FILENAME_3 <boost/functional/forward_adapter.hpp> 274 # define BOOST_PP_ITERATION_LIMITS (0,limit3) 275 # include BOOST_PP_ITERATE() 276 277 # else 278 279 # // I is the loop counter 280 # if limit2 && limit3 281 # define I (BOOST_PP_ITERATION_1 << 16 | BOOST_PP_ITERATION_2 << 8 | \ 282 BOOST_PP_ITERATION_3) 283 # elif limit2 284 # define I (BOOST_PP_ITERATION_1 << 8 | BOOST_PP_ITERATION_2) 285 # else 286 # define I BOOST_PP_ITERATION_1 287 # endif 288 289 # if I < count 290 291 # // Done for this arity? Increment N 292 # if (I+2 >> N+1) 293 # if N == 0 294 # undef N 295 # define N 1 296 # elif N == 1 297 # undef N 298 # define N 2 299 # elif N == 2 300 # undef N 301 # define N 3 302 # elif N == 3 303 # undef N 304 # define N 4 305 # elif N == 4 306 # undef N 307 # define N 5 308 # elif N == 5 309 # undef N 310 # define N 6 311 # elif N == 6 312 # undef N 313 # define N 7 314 # elif N == 7 315 # undef N 316 # define N 8 317 # elif N == 8 318 # undef N 319 # define N 9 320 # elif N == 9 321 # undef N 322 # define N 10 323 # elif N == 10 324 # undef N 325 # define N 11 326 # elif N == 11 327 # undef N 328 # define N 12 329 # elif N == 12 330 # undef N 331 # define N 13 332 # elif N == 13 333 # undef N 334 # define N 14 335 # elif N == 14 336 # undef N 337 # define N 15 338 # elif N == 15 339 # undef N 340 # define N 16 341 # endif 342 343 }; 344 345 template< class Self, BOOST_PP_ENUM_PARAMS(N,typename T) > 346 struct forward_adapter_result::apply< Self(BOOST_PP_ENUM_PARAMS(N,T)) > 347 : boost::result_of< 348 BOOST_DEDUCED_TYPENAME c<Self>::t(BOOST_PP_ENUM_BINARY_PARAMS(N, 349 typename q<T,>::t& BOOST_PP_INTERCEPT)) > 350 { }; 351 352 template< class MD, class F, class FC > 353 struct forward_adapter_impl<MD,F,FC,BOOST_PP_DEC(N),N> 354 { 355 template< BOOST_PP_ENUM_PARAMS(N,typename T) > 356 inline typename boost::result_of< F( 357 BOOST_PP_ENUM_BINARY_PARAMS(N,T,& BOOST_PP_INTERCEPT)) >::type 358 operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,& BOOST_PP_INTERCEPT)); 359 }; 360 361 template< class MD, class F, class FC, int MinArity > 362 struct forward_adapter_impl<MD,F,FC,N,MinArity> 363 : forward_adapter_impl<MD,F,FC,BOOST_PP_DEC(N),MinArity> 364 { 365 using forward_adapter_impl<MD,F,FC,BOOST_PP_DEC(N),MinArity>::operator(); 366 367 # endif 368 369 # // Zero based count for each arity would be I-(1<<N)+2, but we don't 370 # // need it, unless we need a nicer order. 371 372 # // Macros for the parameter's type modifiers. 373 # if I & 0x000001 374 # define PT0 T0 & 375 # else 376 # define PT0 T0 const & 377 # endif 378 # if I & 0x000002 379 # define PT1 T1 & 380 # else 381 # define PT1 T1 const & 382 # endif 383 # if I & 0x000004 384 # define PT2 T2 & 385 # else 386 # define PT2 T2 const & 387 # endif 388 # if I & 0x000008 389 # define PT3 T3 & 390 # else 391 # define PT3 T3 const & 392 # endif 393 # if I & 0x000010 394 # define PT4 T4 & 395 # else 396 # define PT4 T4 const & 397 # endif 398 # if I & 0x000020 399 # define PT5 T5 & 400 # else 401 # define PT5 T5 const & 402 # endif 403 # if I & 0x000040 404 # define PT6 T6 & 405 # else 406 # define PT6 T6 const & 407 # endif 408 # if I & 0x000080 409 # define PT7 T7 & 410 # else 411 # define PT7 T7 const & 412 # endif 413 # if I & 0x000100 414 # define PT8 T8 & 415 # else 416 # define PT8 T8 const & 417 # endif 418 # if I & 0x000200 419 # define PT9 T9 & 420 # else 421 # define PT9 T9 const & 422 # endif 423 # if I & 0x000400 424 # define PT10 T10 & 425 # else 426 # define PT10 T10 const & 427 # endif 428 # if I & 0x000800 429 # define PT11 T11 & 430 # else 431 # define PT11 T11 const & 432 # endif 433 # if I & 0x001000 434 # define PT12 T12 & 435 # else 436 # define PT12 T12 const & 437 # endif 438 # if I & 0x002000 439 # define PT13 T13 & 440 # else 441 # define PT13 T13 const & 442 # endif 443 # if I & 0x004000 444 # define PT14 T14 & 445 # else 446 # define PT14 T14 const & 447 # endif 448 # if I & 0x008000 449 # define PT15 T15 & 450 # else 451 # define PT15 T15 const & 452 # endif 453 454 # if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1400)) 455 template< BOOST_PP_ENUM_PARAMS(N,typename T) > 456 inline typename boost::result_of< FC(BOOST_PP_ENUM_PARAMS(N,PT)) 457 >::type 458 operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,PT,a)) const 459 { 460 return static_cast<MD const* const>(this) 461 ->target_function()(BOOST_PP_ENUM_PARAMS(N,a)); 462 } 463 template< BOOST_PP_ENUM_PARAMS(N,typename T) > 464 inline typename boost::result_of< F(BOOST_PP_ENUM_PARAMS(N,PT)) 465 >::type 466 operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,PT,a)) 467 { 468 return static_cast<MD* const>(this) 469 ->target_function()(BOOST_PP_ENUM_PARAMS(N,a)); 470 } 471 # else 472 BOOST_TMP_MACRO(BOOST_PP_ENUM_PARAMS(N,typename T), 473 BOOST_PP_ENUM_PARAMS(N,PT), BOOST_PP_ENUM_BINARY_PARAMS(N,PT,a), 474 BOOST_PP_ENUM_PARAMS(N,a) ) 475 // ...generates uglier code but is faster - it caches ENUM_* 476 # endif 477 478 # undef PT0 479 # undef PT1 480 # undef PT2 481 # undef PT3 482 # undef PT4 483 # undef PT5 484 # undef PT6 485 # undef PT7 486 # undef PT8 487 # undef PT9 488 # undef PT10 489 # undef PT11 490 # undef PT12 491 # undef PT13 492 # undef PT14 493 # undef PT15 494 495 # endif // I < count 496 497 # undef I 498 # endif // defined(BOOST_PP_IS_ITERATING) 499 500 #endif // include guard 501 502