]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | |
2 | // (C) Copyright Tobias Schwinger | |
3 | // | |
4 | // Use modification and distribution are subject to the boost Software License, | |
5 | // Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). | |
6 | ||
7 | //------------------------------------------------------------------------------ | |
8 | ||
9 | #ifndef BOOST_FT_COMPONENTS_HPP_INCLUDED | |
10 | #define BOOST_FT_COMPONENTS_HPP_INCLUDED | |
11 | ||
12 | #include <cstddef> | |
13 | ||
14 | #include <boost/config.hpp> | |
15 | ||
16 | #include <boost/detail/workaround.hpp> | |
17 | #include <boost/mpl/aux_/lambda_support.hpp> | |
18 | ||
19 | #include <boost/type_traits/integral_constant.hpp> | |
20 | ||
21 | #include <boost/mpl/if.hpp> | |
22 | #include <boost/mpl/integral_c.hpp> | |
23 | #include <boost/mpl/vector/vector0.hpp> | |
24 | ||
25 | #if BOOST_WORKAROUND(__BORLANDC__, <= 0x565) | |
26 | # include <boost/type_traits/remove_cv.hpp> | |
27 | ||
28 | # include <boost/mpl/identity.hpp> | |
29 | # include <boost/mpl/bitand.hpp> | |
30 | # include <boost/mpl/vector/vector10.hpp> | |
31 | # include <boost/mpl/front.hpp> | |
32 | # include <boost/mpl/begin.hpp> | |
33 | # include <boost/mpl/advance.hpp> | |
34 | # include <boost/mpl/iterator_range.hpp> | |
35 | # include <boost/mpl/joint_view.hpp> | |
36 | # include <boost/mpl/equal_to.hpp> | |
37 | # include <boost/mpl/copy.hpp> | |
38 | # include <boost/mpl/front_inserter.hpp> | |
39 | ||
40 | # include <boost/function_types/detail/classifier.hpp> | |
41 | #endif | |
42 | ||
43 | #ifndef BOOST_FT_NO_CV_FUNC_SUPPORT | |
44 | # include <boost/mpl/remove.hpp> | |
45 | #endif | |
46 | ||
47 | #include <boost/function_types/config/config.hpp> | |
48 | ||
49 | # if BOOST_FT_MAX_ARITY < 10 | |
50 | # include <boost/mpl/vector/vector10.hpp> | |
51 | # elif BOOST_FT_MAX_ARITY < 20 | |
52 | # include <boost/mpl/vector/vector20.hpp> | |
53 | # elif BOOST_FT_MAX_ARITY < 30 | |
54 | # include <boost/mpl/vector/vector30.hpp> | |
55 | # elif BOOST_FT_MAX_ARITY < 40 | |
56 | # include <boost/mpl/vector/vector40.hpp> | |
57 | # elif BOOST_FT_MAX_ARITY < 50 | |
58 | # include <boost/mpl/vector/vector50.hpp> | |
59 | # endif | |
60 | ||
61 | #include <boost/function_types/detail/class_transform.hpp> | |
62 | #include <boost/function_types/property_tags.hpp> | |
63 | ||
64 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
65 | ||
66 | namespace boost | |
67 | { | |
68 | namespace function_types | |
69 | { | |
70 | ||
71 | using mpl::placeholders::_; | |
72 | ||
73 | template< typename T, typename ClassTypeTransform = add_reference<_> > | |
74 | struct components; | |
75 | ||
76 | namespace detail | |
77 | { | |
78 | template<typename T, typename L> struct components_impl; | |
79 | #if BOOST_WORKAROUND(__BORLANDC__, <= 0x565) | |
80 | template<typename T, typename OrigT, typename L> struct components_bcc; | |
81 | #endif | |
82 | } | |
83 | ||
84 | template<typename T, typename ClassTypeTransform> | |
85 | struct components | |
86 | #if !BOOST_WORKAROUND(__BORLANDC__, <= 0x565) | |
87 | : detail::components_impl<T, ClassTypeTransform> | |
88 | #else | |
89 | : detail::components_bcc<typename remove_cv<T>::type,T, | |
90 | ClassTypeTransform> | |
91 | #endif | |
92 | { | |
93 | typedef components<T,ClassTypeTransform> type; | |
94 | ||
95 | BOOST_MPL_AUX_LAMBDA_SUPPORT(2,components,(T,ClassTypeTransform)) | |
96 | }; | |
97 | ||
98 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
99 | ||
100 | namespace detail { | |
101 | ||
102 | struct components_mpl_sequence_tag; | |
103 | ||
104 | struct components_non_func_base | |
105 | { | |
106 | typedef mpl::vector0<> types; | |
107 | typedef void function_arity; | |
108 | ||
109 | typedef detail::constant<0> bits; | |
110 | typedef detail::constant<0> mask; | |
111 | ||
112 | typedef components_mpl_sequence_tag tag; | |
113 | }; | |
114 | ||
115 | template | |
116 | < typename Components | |
117 | , typename IfTagged | |
118 | , typename ThenTag | |
119 | , typename DefaultBase = components_non_func_base | |
120 | > | |
121 | struct retagged_if | |
122 | : mpl::if_ | |
123 | < detail::represents_impl<Components, IfTagged> | |
124 | , detail::changed_tag<Components,IfTagged,ThenTag> | |
125 | , DefaultBase | |
126 | >::type | |
127 | { }; | |
128 | ||
129 | // We detect plain function types and function references as function | |
130 | // pointers by recursive instantiation of components_impl. | |
131 | // The third specialization of components_impl makes sure the recursion | |
132 | // terminates (when adding pointers). | |
133 | template<typename T, typename L> | |
134 | struct components_impl | |
135 | : detail::retagged_if | |
136 | < detail::components_impl<T*,L> | |
137 | , pointer_tag, /* --> */ function_tag > | |
138 | { }; | |
139 | template<typename T, typename L> | |
140 | struct components_impl<T&, L> | |
141 | : detail::retagged_if | |
142 | < detail::components_impl<T*,L> | |
143 | , pointer_tag, /* --> */ reference_tag > | |
144 | { }; | |
145 | ||
146 | #if !BOOST_FT_NO_CV_FUNC_SUPPORT | |
147 | // Retry the type with a member pointer attached to detect cv functions | |
148 | class a_class; | |
149 | ||
150 | template<typename Base, typename T, typename L> | |
151 | struct cv_func_base | |
152 | : detail::retagged_if<Base,member_pointer_tag,function_tag> | |
153 | { | |
154 | typedef typename | |
155 | mpl::remove | |
156 | < typename Base::types | |
157 | , typename detail::class_transform<a_class,L>::type>::type | |
158 | types; | |
159 | }; | |
160 | ||
161 | template<typename T, typename L> | |
162 | struct components_impl<T*, L> | |
163 | : mpl::if_ | |
164 | < detail::represents_impl< detail::components_impl<T a_class::*, L> | |
165 | , member_pointer_tag > | |
166 | , detail::cv_func_base< detail::components_impl<T a_class::*, L>, T, L> | |
167 | , components_non_func_base | |
168 | >::type | |
169 | { }; | |
170 | ||
171 | template<typename T, typename L> | |
172 | struct components_impl<T a_class::*, L> | |
173 | : components_non_func_base | |
174 | { }; | |
175 | #else | |
176 | template<typename T, typename L> | |
177 | struct components_impl<T*, L> | |
178 | : components_non_func_base | |
179 | { }; | |
180 | #endif | |
181 | ||
182 | template<typename T, typename L> | |
183 | struct components_impl<T* const, L> | |
184 | : components_impl<T*,L> | |
185 | { }; | |
186 | ||
187 | template<typename T, typename L> | |
188 | struct components_impl<T* volatile, L> | |
189 | : components_impl<T*,L> | |
190 | { }; | |
191 | ||
192 | template<typename T, typename L> | |
193 | struct components_impl<T* const volatile, L> | |
194 | : components_impl<T*,L> | |
195 | { }; | |
196 | ||
197 | template<typename T, typename L> | |
198 | struct components_impl<T const, L> | |
199 | : components_impl<T,L> | |
200 | { }; | |
201 | ||
202 | template<typename T, typename L> | |
203 | struct components_impl<T volatile, L> | |
204 | : components_impl<T,L> | |
205 | { }; | |
206 | ||
207 | template<typename T, typename L> | |
208 | struct components_impl<T const volatile, L> | |
209 | : components_impl<T,L> | |
210 | { }; | |
211 | ||
212 | ||
213 | template<typename T, class C> | |
214 | struct member_obj_ptr_result | |
215 | { typedef T & type; }; | |
216 | ||
217 | template<typename T, class C> | |
218 | struct member_obj_ptr_result<T, C const> | |
219 | { typedef T const & type; }; | |
220 | ||
221 | template<typename T, class C> | |
222 | struct member_obj_ptr_result<T, C volatile> | |
223 | { typedef T volatile & type; }; | |
224 | ||
225 | template<typename T, class C> | |
226 | struct member_obj_ptr_result<T, C const volatile> | |
227 | { typedef T const volatile & type; }; | |
228 | ||
229 | template<typename T, class C> | |
230 | struct member_obj_ptr_result<T &, C> | |
231 | { typedef T & type; }; | |
232 | ||
233 | template<typename T, class C> | |
234 | struct member_obj_ptr_result<T &, C const> | |
235 | { typedef T & type; }; | |
236 | ||
237 | template<typename T, class C> | |
238 | struct member_obj_ptr_result<T &, C volatile> | |
239 | { typedef T & type; }; | |
240 | ||
241 | template<typename T, class C> | |
242 | struct member_obj_ptr_result<T &, C const volatile> | |
243 | { typedef T & type; }; | |
244 | ||
245 | template<typename T, class C, typename L> | |
246 | struct member_obj_ptr_components | |
247 | : member_object_pointer_base | |
248 | { | |
249 | typedef function_types::components<T C::*, L> type; | |
250 | typedef components_mpl_sequence_tag tag; | |
251 | ||
252 | typedef mpl::integral_c<std::size_t,1> function_arity; | |
253 | ||
254 | typedef mpl::vector2< typename detail::member_obj_ptr_result<T,C>::type, | |
255 | typename detail::class_transform<C,L>::type > types; | |
256 | }; | |
257 | ||
258 | #if !BOOST_WORKAROUND(__BORLANDC__, <= 0x565) | |
259 | # define BOOST_FT_variations BOOST_FT_pointer|BOOST_FT_member_pointer | |
260 | ||
261 | template<typename T, class C, typename L> | |
262 | struct components_impl<T C::*, L> | |
263 | : member_obj_ptr_components<T,C,L> | |
264 | { }; | |
265 | ||
266 | #else | |
267 | # define BOOST_FT_variations BOOST_FT_pointer | |
268 | ||
269 | // This workaround removes the member pointer from the type to allow | |
270 | // detection of member function pointers with BCC. | |
271 | template<typename T, typename C, typename L> | |
272 | struct components_impl<T C::*, L> | |
273 | : detail::retagged_if | |
274 | < detail::components_impl<typename boost::remove_cv<T>::type *, L> | |
275 | , pointer_tag, /* --> */ member_function_pointer_tag | |
276 | , member_obj_ptr_components<T,C,L> > | |
277 | { }; | |
278 | ||
279 | // BCC lets us test the cv-qualification of a function type by template | |
280 | // partial specialization - so we use this bug feature to find out the | |
281 | // member function's cv-qualification (unfortunately there are some | |
282 | // invisible modifiers that impose some limitations on these types even if | |
283 | // we remove the qualifiers, So we cannot exploit the same bug to make the | |
284 | // library work for cv-qualified function types). | |
285 | template<typename T> struct encode_cv | |
286 | { typedef char (& type)[1]; BOOST_STATIC_CONSTANT(std::size_t, value = 1); }; | |
287 | template<typename T> struct encode_cv<T const *> | |
288 | { typedef char (& type)[2]; BOOST_STATIC_CONSTANT(std::size_t, value = 2); }; | |
289 | template<typename T> struct encode_cv<T volatile *> | |
290 | { typedef char (& type)[3]; BOOST_STATIC_CONSTANT(std::size_t, value = 3); }; | |
291 | template<typename T> struct encode_cv<T const volatile *> | |
292 | { typedef char (& type)[4]; BOOST_STATIC_CONSTANT(std::size_t, value = 4); }; | |
293 | ||
294 | // For member function pointers we have to use a function template (partial | |
295 | // template specialization for a member pointer drops the cv qualification | |
296 | // of the function type). | |
297 | template<typename T, typename C> | |
298 | typename encode_cv<T *>::type mfp_cv_tester(T C::*); | |
299 | ||
300 | template<typename T> struct encode_mfp_cv | |
301 | { | |
302 | BOOST_STATIC_CONSTANT(std::size_t, value = | |
303 | sizeof(detail::mfp_cv_tester((T)0L))); | |
304 | }; | |
305 | ||
306 | // Associate bits with the CV codes above. | |
307 | template<std::size_t> struct cv_tag_mfp_impl; | |
308 | ||
309 | template<typename T> struct cv_tag_mfp | |
310 | : detail::cv_tag_mfp_impl | |
311 | < ::boost::function_types::detail::encode_mfp_cv<T>::value > | |
312 | { }; | |
313 | ||
314 | template<> struct cv_tag_mfp_impl<1> : non_cv { }; | |
315 | template<> struct cv_tag_mfp_impl<2> : const_non_volatile { }; | |
316 | template<> struct cv_tag_mfp_impl<3> : volatile_non_const { }; | |
317 | template<> struct cv_tag_mfp_impl<4> : cv_qualified { }; | |
318 | ||
319 | // Metafunction to decode the cv code and apply it to a type. | |
320 | // We add a pointer, because otherwise cv-qualifiers won't stick (another bug). | |
321 | template<typename T, std::size_t CV> struct decode_cv; | |
322 | ||
323 | template<typename T> struct decode_cv<T,1> : mpl::identity<T *> {}; | |
324 | template<typename T> struct decode_cv<T,2> : mpl::identity<T const *> {}; | |
325 | template<typename T> struct decode_cv<T,3> : mpl::identity<T volatile *> {}; | |
326 | template<typename T> struct decode_cv<T,4> | |
327 | : mpl::identity<T const volatile *> {}; | |
328 | ||
329 | // The class type transformation comes after adding cv-qualifiers. We have | |
330 | // wrap it to remove the pointer added in decode_cv_impl. | |
331 | template<typename T, typename L> struct bcc_class_transform_impl; | |
332 | template<typename T, typename L> struct bcc_class_transform_impl<T *, L> | |
333 | : class_transform<T,L> | |
334 | { }; | |
335 | ||
336 | template<typename T, typename D, typename L> struct bcc_class_transform | |
337 | : bcc_class_transform_impl | |
338 | < typename decode_cv | |
339 | < T | |
340 | , ::boost::function_types::detail::encode_mfp_cv<D>::value | |
341 | >::type | |
342 | , L | |
343 | > | |
344 | { }; | |
345 | ||
346 | // After extracting the member pointee from the type the class type is still | |
347 | // in the type (somewhere -- you won't see with RTTI, that is) and that type | |
348 | // is flagged unusable and *not* identical to the nonmember function type. | |
349 | // We can, however, decompose this type via components_impl but surprisingly | |
350 | // a pointer to the const qualified class type pops up again as the first | |
351 | // parameter type. | |
352 | // We have to replace this type with the properly cv-qualified and | |
353 | // transformed class type, integrate the cv qualification into the bits. | |
354 | template<typename Base, typename MFP, typename OrigT, typename L> | |
355 | struct mfp_components; | |
356 | ||
357 | ||
358 | template<typename Base, typename T, typename C, typename OrigT, typename L> | |
359 | struct mfp_components<Base,T C::*,OrigT,L> | |
360 | { | |
361 | private: | |
362 | typedef typename mpl::front<typename Base::types>::type result_type; | |
363 | typedef typename detail::bcc_class_transform<C,OrigT,L>::type class_type; | |
364 | ||
365 | typedef mpl::vector2<result_type, class_type> result_and_class_type; | |
366 | ||
367 | typedef typename | |
368 | mpl::advance | |
369 | < typename mpl::begin<typename Base::types>::type | |
370 | , typename mpl::if_ | |
371 | < mpl::equal_to< typename detail::classifier<OrigT>::function_arity | |
372 | , typename Base::function_arity > | |
373 | , mpl::integral_c<int,2> , mpl::integral_c<int,1> | |
374 | >::type | |
375 | >::type | |
376 | from; | |
377 | typedef typename mpl::end<typename Base::types>::type to; | |
378 | ||
379 | typedef mpl::iterator_range<from,to> param_types; | |
380 | ||
381 | typedef mpl::joint_view< result_and_class_type, param_types> types_view; | |
382 | public: | |
383 | ||
384 | typedef typename | |
385 | mpl::reverse_copy<types_view, mpl::front_inserter< mpl::vector0<> > >::type | |
386 | types; | |
387 | ||
388 | typedef typename | |
389 | function_types::tag< Base, detail::cv_tag_mfp<OrigT> >::bits | |
390 | bits; | |
391 | ||
392 | typedef typename Base::mask mask; | |
393 | ||
394 | typedef typename detail::classifier<OrigT>::function_arity function_arity; | |
395 | ||
396 | typedef components_mpl_sequence_tag tag; | |
397 | }; | |
398 | ||
399 | // Now put it all together: detect cv-qualification of function types and do | |
400 | // the weird transformations above for member function pointers. | |
401 | template<typename T, typename OrigT, typename L> | |
402 | struct components_bcc | |
403 | : mpl::if_ | |
404 | < detail::represents_impl< detail::components_impl<T,L> | |
405 | , member_function_pointer_tag> | |
406 | , detail::mfp_components<detail::components_impl<T,L>,T,OrigT,L> | |
407 | , detail::components_impl<T,L> | |
408 | >::type | |
409 | { }; | |
410 | ||
411 | #endif // end of BORLAND WORKAROUND | |
412 | ||
413 | #define BOOST_FT_al_path boost/function_types/detail/components_impl | |
414 | #include <boost/function_types/detail/pp_loop.hpp> | |
415 | ||
416 | } } // namespace function_types::detail | |
417 | ||
418 | } // namespace ::boost | |
419 | ||
420 | #include <boost/function_types/detail/components_as_mpl_sequence.hpp> | |
421 | #include <boost/function_types/detail/retag_default_cc.hpp> | |
422 | ||
423 | #endif | |
424 |