]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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/detail/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: | |
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 | ||
89 | Function & target_function() { return *this; } | |
90 | 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: | |
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 | ||
112 | 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: | |
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 | ||
134 | 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> | |
171 | 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 | |
180 | operator()() const | |
181 | { | |
182 | return static_cast<MD const*>(this)->target_function()(); | |
183 | } | |
184 | ||
185 | inline typename boost::result_of< F() >::type | |
186 | 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 | |
265 | 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 | |
275 | 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 |