lightweight_forward_adapter.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. /*=============================================================================
  2. Copyright (c) 2007 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_LIGHTWEIGHT_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/cat.hpp>
  12. # include <boost/preprocessor/iteration/iterate.hpp>
  13. # include <boost/preprocessor/repetition/enum.hpp>
  14. # include <boost/preprocessor/repetition/enum_params.hpp>
  15. # include <boost/preprocessor/repetition/enum_binary_params.hpp>
  16. # include <boost/preprocessor/facilities/intercept.hpp>
  17. # include <boost/utility/result_of.hpp>
  18. # include <boost/ref.hpp>
  19. # ifndef BOOST_FUNCTIONAL_LIGHTWEIGHT_FORWARD_ADAPTER_MAX_ARITY
  20. # define BOOST_FUNCTIONAL_LIGHTWEIGHT_FORWARD_ADAPTER_MAX_ARITY 10
  21. # elif BOOST_FUNCTIONAL_FORDWARD_ADAPTER_MAX_ARITY < 3
  22. # undef BOOST_FUNCTIONAL_LIGHTWEIGHT_FORWARD_ADAPTER_MAX_ARITY
  23. # define BOOST_FUNCTIONAL_LIGHTWEIGHT_FORWARD_ADAPTER_MAX_ARITY 3
  24. # endif
  25. namespace boost
  26. {
  27. template< typename Function, int Arity_Or_MinArity = -1, int MaxArity = -1 >
  28. class lightweight_forward_adapter;
  29. //----- ---- --- -- - - - -
  30. namespace detail
  31. {
  32. template< class MostDerived, typename Function, typename FunctionConst,
  33. int Arity, int MinArity >
  34. struct lightweight_forward_adapter_impl;
  35. struct lightweight_forward_adapter_result
  36. {
  37. template< typename Sig > struct apply;
  38. // Utility metafunction for argument transform
  39. template< typename T > struct x { typedef T const& t; };
  40. template< typename T > struct x< boost::reference_wrapper<T> >
  41. { typedef T& t; };
  42. template< typename T > struct x<T&> : x<T> { };
  43. template< typename T > struct x<T const&> : x<T> { };
  44. template< typename T > struct x<T const> : x<T> { };
  45. // Utility metafunction to choose target function qualification
  46. template< typename T > struct c
  47. { typedef typename T::target_function_t t; };
  48. template< typename T > struct c<T& >
  49. { typedef typename T::target_function_t t; };
  50. template< typename T > struct c<T const >
  51. { typedef typename T::target_function_const_t t; };
  52. template< typename T > struct c<T const&>
  53. { typedef typename T::target_function_const_t t; };
  54. };
  55. }
  56. # define BOOST_TMP_MACRO(f,fn,fc) \
  57. boost::detail::lightweight_forward_adapter_impl< \
  58. lightweight_forward_adapter<f,Arity_Or_MinArity,MaxArity>, fn, fc, \
  59. (MaxArity!=-1? MaxArity :Arity_Or_MinArity!=-1? Arity_Or_MinArity \
  60. :BOOST_FUNCTIONAL_LIGHTWEIGHT_FORWARD_ADAPTER_MAX_ARITY), \
  61. (Arity_Or_MinArity!=-1? Arity_Or_MinArity : 0) >
  62. template< typename Function, int Arity_Or_MinArity, int MaxArity >
  63. class lightweight_forward_adapter
  64. : public BOOST_TMP_MACRO(Function,Function,Function const)
  65. , private Function
  66. {
  67. public:
  68. lightweight_forward_adapter(Function const& f = Function())
  69. : Function(f)
  70. { }
  71. typedef Function target_function_t;
  72. typedef Function const target_function_const_t;
  73. Function & target_function() { return *this; }
  74. Function const & target_function() const { return *this; }
  75. template< typename Sig > struct result
  76. : detail::lightweight_forward_adapter_result::template apply<Sig>
  77. { };
  78. using BOOST_TMP_MACRO(Function,Function, Function const)::operator();
  79. };
  80. template< typename Function, int Arity_Or_MinArity, int MaxArity >
  81. class lightweight_forward_adapter< Function const, Arity_Or_MinArity,
  82. MaxArity >
  83. : public BOOST_TMP_MACRO(Function const, Function const, Function const)
  84. , private Function
  85. {
  86. public:
  87. lightweight_forward_adapter(Function const& f = Function())
  88. : Function(f)
  89. { }
  90. typedef Function const target_function_t;
  91. typedef Function const target_function_const_t;
  92. Function const & target_function() const { return *this; }
  93. template< typename Sig > struct result
  94. : detail::lightweight_forward_adapter_result::template apply<Sig>
  95. { };
  96. using BOOST_TMP_MACRO(Function const,Function const, Function const)
  97. ::operator();
  98. };
  99. template< typename Function, int Arity_Or_MinArity, int MaxArity >
  100. class lightweight_forward_adapter< Function &, Arity_Or_MinArity, MaxArity >
  101. : public BOOST_TMP_MACRO(Function&, Function, Function)
  102. {
  103. Function& ref_function;
  104. public:
  105. lightweight_forward_adapter(Function& f)
  106. : ref_function(f)
  107. { }
  108. typedef Function target_function_t;
  109. typedef Function target_function_const_t;
  110. Function & target_function() const { return this->ref_function; }
  111. template< typename Sig > struct result
  112. : detail::lightweight_forward_adapter_result::template apply<Sig>
  113. { };
  114. using BOOST_TMP_MACRO(Function&, Function, Function)::operator();
  115. };
  116. #undef BOOST_TMP_MACRO
  117. namespace detail
  118. {
  119. template< class Self >
  120. struct lightweight_forward_adapter_result::apply< Self() >
  121. : boost::result_of< BOOST_DEDUCED_TYPENAME c<Self>::t() >
  122. { };
  123. // When operator() doesn't have any parameters, it can't
  124. // be templatized and can't use SFINAE, so intead use class
  125. // template parameter SFINAE to decide whether to instantiate it.
  126. template <typename T, typename R = void>
  127. struct lightweight_forward_adapter_sfinae
  128. {
  129. typedef T type;
  130. };
  131. // This is the fallback for when there isn't an operator()(),
  132. // need to create an operator() that will never instantiate
  133. // so that using parent::operator() will work okay.
  134. template< class MD, class F, class FC, class Enable = void>
  135. struct lightweight_forward_adapter_impl_zero
  136. : lightweight_forward_adapter_result
  137. {
  138. template <typename T> struct never_instantiate {};
  139. template <typename T>
  140. typename never_instantiate<T>::type operator()(T) const {}
  141. };
  142. template< class MD, class F, class FC>
  143. struct lightweight_forward_adapter_impl_zero<MD, F, FC,
  144. typename lightweight_forward_adapter_sfinae<typename boost::result_of< FC() >::type>::type>
  145. : lightweight_forward_adapter_result
  146. {
  147. inline typename boost::result_of< FC() >::type
  148. operator()() const
  149. {
  150. return static_cast<MD const*>(this)->target_function()();
  151. }
  152. inline typename boost::result_of< F() >::type
  153. operator()()
  154. {
  155. return static_cast<MD*>(this)->target_function()();
  156. }
  157. };
  158. template< class MD, class F, class FC >
  159. struct lightweight_forward_adapter_impl<MD,F,FC,0,0>
  160. : lightweight_forward_adapter_impl_zero<MD,F,FC>
  161. {
  162. };
  163. # define BOOST_PP_FILENAME_1 \
  164. <boost/functional/lightweight_forward_adapter.hpp>
  165. # define BOOST_PP_ITERATION_LIMITS \
  166. (1,BOOST_FUNCTIONAL_LIGHTWEIGHT_FORWARD_ADAPTER_MAX_ARITY)
  167. # include BOOST_PP_ITERATE()
  168. } // namespace detail
  169. template<class F, int A0, int A1>
  170. struct result_of<boost::lightweight_forward_adapter<F,A0,A1> const ()>
  171. : boost::detail::lightweight_forward_adapter_result::template apply<
  172. boost::lightweight_forward_adapter<F,A0,A1> const () >
  173. { };
  174. template<class F, int A0, int A1>
  175. struct result_of<boost::lightweight_forward_adapter<F,A0,A1>()>
  176. : boost::detail::lightweight_forward_adapter_result::template apply<
  177. boost::lightweight_forward_adapter<F,A0,A1>() >
  178. { };
  179. template<class F, int A0, int A1>
  180. struct result_of<boost::lightweight_forward_adapter<F,A0,A1> const& ()>
  181. : boost::detail::lightweight_forward_adapter_result::template apply<
  182. boost::lightweight_forward_adapter<F,A0,A1> const () >
  183. { };
  184. template<class F, int A0, int A1>
  185. struct result_of<boost::lightweight_forward_adapter<F,A0,A1>& ()>
  186. : boost::detail::lightweight_forward_adapter_result::template apply<
  187. boost::lightweight_forward_adapter<F,A0,A1>() >
  188. { };
  189. }
  190. # define BOOST_FUNCTIONAL_LIGHTWEIGHT_FORWARD_ADAPTER_HPP_INCLUDED
  191. # else // defined(BOOST_PP_IS_ITERATING)
  192. # define N BOOST_PP_ITERATION()
  193. template< class Self, BOOST_PP_ENUM_PARAMS(N,typename T) >
  194. struct lightweight_forward_adapter_result::apply<
  195. Self (BOOST_PP_ENUM_PARAMS(N,T)) >
  196. : boost::result_of<
  197. BOOST_DEDUCED_TYPENAME c<Self>::t (BOOST_PP_ENUM_BINARY_PARAMS(N,
  198. typename x<T,>::t BOOST_PP_INTERCEPT)) >
  199. { };
  200. template< class MD, class F, class FC >
  201. struct lightweight_forward_adapter_impl<MD,F,FC,BOOST_PP_DEC(N),N>
  202. : lightweight_forward_adapter_result
  203. {
  204. template< BOOST_PP_ENUM_PARAMS(N,typename T) >
  205. inline typename boost::result_of< F(BOOST_PP_ENUM_BINARY_PARAMS(N,
  206. T,const& BOOST_PP_INTERCEPT)) >::type
  207. operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,& BOOST_PP_INTERCEPT));
  208. };
  209. template< class MD, class F, class FC, int MinArity >
  210. struct lightweight_forward_adapter_impl<MD,F,FC,N,MinArity>
  211. : lightweight_forward_adapter_impl<MD,F,FC,BOOST_PP_DEC(N),MinArity>
  212. {
  213. using lightweight_forward_adapter_impl<MD,F,FC,BOOST_PP_DEC(N),
  214. MinArity>::operator();
  215. # define M(z,i,d) \
  216. static_cast<typename d::template x<T##i>::t>(a##i)
  217. template< BOOST_PP_ENUM_PARAMS(N,typename T) >
  218. inline typename lightweight_forward_adapter_result::template apply<
  219. MD const (BOOST_PP_ENUM_BINARY_PARAMS(N,
  220. T,const& BOOST_PP_INTERCEPT)) >::type
  221. operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,const& a)) const
  222. {
  223. typedef lightweight_forward_adapter_result _;
  224. return static_cast<MD const*>(this)->target_function()(
  225. BOOST_PP_ENUM(N,M,_));
  226. }
  227. template< BOOST_PP_ENUM_PARAMS(N,typename T) >
  228. inline typename lightweight_forward_adapter_result::template apply<
  229. MD (BOOST_PP_ENUM_BINARY_PARAMS(N,
  230. T,const& BOOST_PP_INTERCEPT)) >::type
  231. operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,const& a))
  232. {
  233. typedef lightweight_forward_adapter_result _;
  234. return static_cast<MD*>(this)->target_function()(
  235. BOOST_PP_ENUM(N,M,_));
  236. }
  237. # undef M
  238. };
  239. # undef N
  240. # endif // defined(BOOST_PP_IS_ITERATING)
  241. #endif // include guard