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