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
66namespace 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
425

source code of boost/boost/function_types/components.hpp