forward_adapter.hpp 15 KB

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