forward_adapter.hpp 16 KB

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