2 // (C) Copyright Tobias Schwinger
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).
7 //------------------------------------------------------------------------------
9 #ifndef BOOST_FT_COMPONENTS_HPP_INCLUDED
10 #define BOOST_FT_COMPONENTS_HPP_INCLUDED
14 #include <boost/config.hpp>
16 #include <boost/detail/workaround.hpp>
17 #include <boost/mpl/aux_/lambda_support.hpp>
18 #include <boost/type_traits/detail/template_arity_spec.hpp>
20 #include <boost/type_traits/integral_constant.hpp>
22 #include <boost/mpl/if.hpp>
23 #include <boost/mpl/integral_c.hpp>
24 #include <boost/mpl/vector/vector0.hpp>
26 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x656))
27 # include <boost/type_traits/remove_cv.hpp>
29 # include <boost/mpl/identity.hpp>
30 # include <boost/mpl/bitand.hpp>
31 # include <boost/mpl/vector/vector10.hpp>
32 # include <boost/mpl/front.hpp>
33 # include <boost/mpl/begin.hpp>
34 # include <boost/mpl/advance.hpp>
35 # include <boost/mpl/iterator_range.hpp>
36 # include <boost/mpl/joint_view.hpp>
37 # include <boost/mpl/equal_to.hpp>
38 # include <boost/mpl/copy.hpp>
39 # include <boost/mpl/front_inserter.hpp>
41 # include <boost/function_types/detail/classifier.hpp>
44 #ifndef BOOST_FT_NO_CV_FUNC_SUPPORT
45 # include <boost/mpl/remove.hpp>
48 #include <boost/function_types/config/config.hpp>
50 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
51 # if BOOST_FT_MAX_ARITY < 10
52 # include <boost/mpl/vector/vector10.hpp>
53 # elif BOOST_FT_MAX_ARITY < 20
54 # include <boost/mpl/vector/vector20.hpp>
55 # elif BOOST_FT_MAX_ARITY < 30
56 # include <boost/mpl/vector/vector30.hpp>
57 # elif BOOST_FT_MAX_ARITY < 40
58 # include <boost/mpl/vector/vector40.hpp>
59 # elif BOOST_FT_MAX_ARITY < 50
60 # include <boost/mpl/vector/vector50.hpp>
63 # include <boost/function_types/detail/classifier.hpp>
66 #include <boost/function_types/detail/class_transform.hpp>
67 #include <boost/function_types/property_tags.hpp>
69 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
73 namespace function_types
76 using mpl::placeholders::_
;
78 template< typename T
, typename ClassTypeTransform
= add_reference
<_
> >
83 template<typename T
, typename L
> struct components_impl
;
84 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x565))
85 template<typename T
, typename OrigT
, typename L
> struct components_bcc
;
89 template<typename T
, typename ClassTypeTransform
>
91 #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x565))
92 : detail::components_impl
<T
, ClassTypeTransform
>
94 : detail::components_bcc
<typename remove_cv
<T
>::type
,T
,
98 typedef components
<T
,ClassTypeTransform
> type
;
100 BOOST_MPL_AUX_LAMBDA_SUPPORT(2,components
,(T
,ClassTypeTransform
))
103 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
107 struct components_mpl_sequence_tag
;
109 struct components_non_func_base
111 typedef mpl::vector0
<> types
;
112 typedef void function_arity
;
114 typedef detail::constant
<0> bits
;
115 typedef detail::constant
<0> mask
;
117 typedef components_mpl_sequence_tag tag
;
121 < typename Components
124 , typename DefaultBase
= components_non_func_base
128 < detail::represents_impl
<Components
, IfTagged
>
129 , detail::changed_tag
<Components
,IfTagged
,ThenTag
>
134 // We detect plain function types and function references as function
135 // pointers by recursive instantiation of components_impl.
136 // The third specialization of components_impl makes sure the recursion
137 // terminates (when adding pointers).
138 template<typename T
, typename L
>
139 struct components_impl
140 : detail::retagged_if
141 < detail::components_impl
<T
*,L
>
142 , pointer_tag
, /* --> */ function_tag
>
144 template<typename T
, typename L
>
145 struct components_impl
<T
&, L
>
146 : detail::retagged_if
147 < detail::components_impl
<T
*,L
>
148 , pointer_tag
, /* --> */ reference_tag
>
151 #if !BOOST_FT_NO_CV_FUNC_SUPPORT
152 // Retry the type with a member pointer attached to detect cv functions
155 template<typename Base
, typename T
, typename L
>
157 : detail::retagged_if
<Base
,member_pointer_tag
,function_tag
>
161 < typename
Base::types
162 , typename
detail::class_transform
<a_class
,L
>::type
>::type
166 template<typename T
, typename L
>
167 struct components_impl
<T
*, L
>
169 < detail::represents_impl
< detail::components_impl
<T
a_class::*, L
>
170 , member_pointer_tag
>
171 , detail::cv_func_base
< detail::components_impl
<T
a_class::*, L
>, T
, L
>
172 , components_non_func_base
176 template<typename T
, typename L
>
177 struct components_impl
<T
a_class::*, L
>
178 : components_non_func_base
181 template<typename T
, typename L
>
182 struct components_impl
<T
*, L
>
183 : components_non_func_base
187 template<typename T
, typename L
>
188 struct components_impl
<T
* const, L
>
189 : components_impl
<T
*,L
>
192 template<typename T
, typename L
>
193 struct components_impl
<T
* volatile, L
>
194 : components_impl
<T
*,L
>
197 template<typename T
, typename L
>
198 struct components_impl
<T
* const volatile, L
>
199 : components_impl
<T
*,L
>
202 template<typename T
, typename L
>
203 struct components_impl
<T
const, L
>
204 : components_impl
<T
,L
>
207 template<typename T
, typename L
>
208 struct components_impl
<T
volatile, L
>
209 : components_impl
<T
,L
>
212 template<typename T
, typename L
>
213 struct components_impl
<T
const volatile, L
>
214 : components_impl
<T
,L
>
218 template<typename T
, class C
>
219 struct member_obj_ptr_result
220 { typedef T
& type
; };
222 template<typename T
, class C
>
223 struct member_obj_ptr_result
<T
, C
const>
224 { typedef T
const & type
; };
226 template<typename T
, class C
>
227 struct member_obj_ptr_result
<T
, C
volatile>
228 { typedef T
volatile & type
; };
230 template<typename T
, class C
>
231 struct member_obj_ptr_result
<T
, C
const volatile>
232 { typedef T
const volatile & type
; };
234 template<typename T
, class C
>
235 struct member_obj_ptr_result
<T
&, C
>
236 { typedef T
& type
; };
238 template<typename T
, class C
>
239 struct member_obj_ptr_result
<T
&, C
const>
240 { typedef T
& type
; };
242 template<typename T
, class C
>
243 struct member_obj_ptr_result
<T
&, C
volatile>
244 { typedef T
& type
; };
246 template<typename T
, class C
>
247 struct member_obj_ptr_result
<T
&, C
const volatile>
248 { typedef T
& type
; };
250 template<typename T
, class C
, typename L
>
251 struct member_obj_ptr_components
252 : member_object_pointer_base
254 typedef function_types::components
<T
C::*, L
> type
;
255 typedef components_mpl_sequence_tag tag
;
257 typedef mpl::integral_c
<std::size_t,1> function_arity
;
259 typedef mpl::vector2
< typename
detail::member_obj_ptr_result
<T
,C
>::type
,
260 typename
detail::class_transform
<C
,L
>::type
> types
;
263 #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x565))
264 # define BOOST_FT_variations BOOST_FT_pointer|BOOST_FT_member_pointer
266 template<typename T
, class C
, typename L
>
267 struct components_impl
<T
C::*, L
>
268 : member_obj_ptr_components
<T
,C
,L
>
272 # define BOOST_FT_variations BOOST_FT_pointer
274 // This workaround removes the member pointer from the type to allow
275 // detection of member function pointers with BCC.
276 template<typename T
, typename C
, typename L
>
277 struct components_impl
<T
C::*, L
>
278 : detail::retagged_if
279 < detail::components_impl
<typename
boost::remove_cv
<T
>::type
*, L
>
280 , pointer_tag
, /* --> */ member_function_pointer_tag
281 , member_obj_ptr_components
<T
,C
,L
> >
284 // BCC lets us test the cv-qualification of a function type by template
285 // partial specialization - so we use this bug feature to find out the
286 // member function's cv-qualification (unfortunately there are some
287 // invisible modifiers that impose some limitations on these types even if
288 // we remove the qualifiers, So we cannot exploit the same bug to make the
289 // library work for cv-qualified function types).
290 template<typename T
> struct encode_cv
291 { typedef char (& type
)[1]; BOOST_STATIC_CONSTANT(std::size_t, value
= 1); };
292 template<typename T
> struct encode_cv
<T
const *>
293 { typedef char (& type
)[2]; BOOST_STATIC_CONSTANT(std::size_t, value
= 2); };
294 template<typename T
> struct encode_cv
<T
volatile *>
295 { typedef char (& type
)[3]; BOOST_STATIC_CONSTANT(std::size_t, value
= 3); };
296 template<typename T
> struct encode_cv
<T
const volatile *>
297 { typedef char (& type
)[4]; BOOST_STATIC_CONSTANT(std::size_t, value
= 4); };
299 // For member function pointers we have to use a function template (partial
300 // template specialization for a member pointer drops the cv qualification
301 // of the function type).
302 template<typename T
, typename C
>
303 typename encode_cv
<T
*>::type
mfp_cv_tester(T
C::*);
305 template<typename T
> struct encode_mfp_cv
307 BOOST_STATIC_CONSTANT(std::size_t, value
=
308 sizeof(detail::mfp_cv_tester((T
)0L)));
311 // Associate bits with the CV codes above.
312 template<std::size_t> struct cv_tag_mfp_impl
;
314 template<typename T
> struct cv_tag_mfp
315 : detail::cv_tag_mfp_impl
316 < ::boost::function_types::detail::encode_mfp_cv
<T
>::value
>
319 template<> struct cv_tag_mfp_impl
<1> : non_cv
{ };
320 template<> struct cv_tag_mfp_impl
<2> : const_non_volatile
{ };
321 template<> struct cv_tag_mfp_impl
<3> : volatile_non_const
{ };
322 template<> struct cv_tag_mfp_impl
<4> : cv_qualified
{ };
324 // Metafunction to decode the cv code and apply it to a type.
325 // We add a pointer, because otherwise cv-qualifiers won't stick (another bug).
326 template<typename T
, std::size_t CV
> struct decode_cv
;
328 template<typename T
> struct decode_cv
<T
,1> : mpl::identity
<T
*> {};
329 template<typename T
> struct decode_cv
<T
,2> : mpl::identity
<T
const *> {};
330 template<typename T
> struct decode_cv
<T
,3> : mpl::identity
<T
volatile *> {};
331 template<typename T
> struct decode_cv
<T
,4>
332 : mpl::identity
<T
const volatile *> {};
334 // The class type transformation comes after adding cv-qualifiers. We have
335 // wrap it to remove the pointer added in decode_cv_impl.
336 template<typename T
, typename L
> struct bcc_class_transform_impl
;
337 template<typename T
, typename L
> struct bcc_class_transform_impl
<T
*, L
>
338 : class_transform
<T
,L
>
341 template<typename T
, typename D
, typename L
> struct bcc_class_transform
342 : bcc_class_transform_impl
345 , ::boost::function_types::detail::encode_mfp_cv
<D
>::value
351 // After extracting the member pointee from the type the class type is still
352 // in the type (somewhere -- you won't see with RTTI, that is) and that type
353 // is flagged unusable and *not* identical to the nonmember function type.
354 // We can, however, decompose this type via components_impl but surprisingly
355 // a pointer to the const qualified class type pops up again as the first
357 // We have to replace this type with the properly cv-qualified and
358 // transformed class type, integrate the cv qualification into the bits.
359 template<typename Base
, typename MFP
, typename OrigT
, typename L
>
360 struct mfp_components
;
363 template<typename Base
, typename T
, typename C
, typename OrigT
, typename L
>
364 struct mfp_components
<Base
,T
C::*,OrigT
,L
>
367 typedef typename
mpl::front
<typename
Base::types
>::type result_type
;
368 typedef typename
detail::bcc_class_transform
<C
,OrigT
,L
>::type class_type
;
370 typedef mpl::vector2
<result_type
, class_type
> result_and_class_type
;
374 < typename
mpl::begin
<typename
Base::types
>::type
376 < mpl::equal_to
< typename
detail::classifier
<OrigT
>::function_arity
377 , typename
Base::function_arity
>
378 , mpl::integral_c
<int,2> , mpl::integral_c
<int,1>
382 typedef typename
mpl::end
<typename
Base::types
>::type to
;
384 typedef mpl::iterator_range
<from
,to
> param_types
;
386 typedef mpl::joint_view
< result_and_class_type
, param_types
> types_view
;
390 mpl::reverse_copy
<types_view
, mpl::front_inserter
< mpl::vector0
<> > >::type
394 function_types::tag
< Base
, detail::cv_tag_mfp
<OrigT
> >::bits
397 typedef typename
Base::mask mask
;
399 typedef typename
detail::classifier
<OrigT
>::function_arity function_arity
;
401 typedef components_mpl_sequence_tag tag
;
404 // Now put it all together: detect cv-qualification of function types and do
405 // the weird transformations above for member function pointers.
406 template<typename T
, typename OrigT
, typename L
>
407 struct components_bcc
409 < detail::represents_impl
< detail::components_impl
<T
,L
>
410 , member_function_pointer_tag
>
411 , detail::mfp_components
<detail::components_impl
<T
,L
>,T
,OrigT
,L
>
412 , detail::components_impl
<T
,L
>
416 #endif // end of BORLAND WORKAROUND
418 #define BOOST_FT_al_path boost/function_types/detail/components_impl
419 #include <boost/function_types/detail/pp_loop.hpp>
421 } } // namespace function_types::detail
423 BOOST_TT_AUX_TEMPLATE_ARITY_SPEC(2,function_types::components
)
425 } // namespace ::boost
427 #include <boost/function_types/detail/components_as_mpl_sequence.hpp>
428 #include <boost/function_types/detail/retag_default_cc.hpp>