PageRenderTime 66ms CodeModel.GetById 11ms app.highlight 50ms RepoModel.GetById 2ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/function_types/components.hpp

http://hadesmem.googlecode.com/
C++ Header | 431 lines | 306 code | 87 blank | 38 comment | 1 complexity | 58bb0f757125182881bb204cbbe46190 MD5 | raw file
  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#include <boost/type_traits/detail/template_arity_spec.hpp>
 19
 20#include <boost/type_traits/integral_constant.hpp>
 21
 22#include <boost/mpl/if.hpp>
 23#include <boost/mpl/integral_c.hpp>
 24#include <boost/mpl/vector/vector0.hpp>
 25
 26#if BOOST_WORKAROUND(__BORLANDC__, <= 0x565)
 27#   include <boost/type_traits/remove_cv.hpp>
 28
 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>
 40
 41#   include <boost/function_types/detail/classifier.hpp>
 42#endif
 43
 44#ifndef BOOST_FT_NO_CV_FUNC_SUPPORT
 45#   include <boost/mpl/remove.hpp>
 46#endif
 47
 48#include <boost/function_types/config/config.hpp>
 49
 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>
 61#   endif
 62#else
 63#   include <boost/function_types/detail/classifier.hpp>
 64#endif
 65
 66#include <boost/function_types/detail/class_transform.hpp>
 67#include <boost/function_types/property_tags.hpp>
 68
 69// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 70
 71namespace boost 
 72{ 
 73  namespace function_types 
 74  {
 75
 76    using mpl::placeholders::_;
 77
 78    template< typename T, typename ClassTypeTransform = add_reference<_> > 
 79    struct components;
 80
 81    namespace detail 
 82    {
 83      template<typename T, typename L> struct components_impl;
 84#if BOOST_WORKAROUND(__BORLANDC__, <= 0x565)
 85      template<typename T, typename OrigT, typename L> struct components_bcc;
 86#endif
 87    }
 88
 89    template<typename T, typename ClassTypeTransform> 
 90    struct components
 91#if !BOOST_WORKAROUND(__BORLANDC__, <= 0x565)
 92      : detail::components_impl<T, ClassTypeTransform>
 93#else
 94      : detail::components_bcc<typename remove_cv<T>::type,T,
 95            ClassTypeTransform>
 96#endif
 97    { 
 98      typedef components<T,ClassTypeTransform> type;
 99
100      BOOST_MPL_AUX_LAMBDA_SUPPORT(2,components,(T,ClassTypeTransform))
101    };
102
103// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
104
105  namespace detail {
106
107    struct components_mpl_sequence_tag; 
108
109    struct components_non_func_base
110    {
111      typedef mpl::vector0<> types;
112      typedef void function_arity;
113
114      typedef detail::constant<0> bits;
115      typedef detail::constant<0> mask;
116
117      typedef components_mpl_sequence_tag tag;
118    };
119
120    template
121    < typename Components
122    , typename IfTagged
123    , typename ThenTag
124    , typename DefaultBase = components_non_func_base
125    >
126    struct retagged_if
127      : mpl::if_
128        < detail::represents_impl<Components, IfTagged>
129        , detail::changed_tag<Components,IfTagged,ThenTag>
130        , DefaultBase
131        >::type
132    { };
133
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 >
143    { };
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 >
149    { };
150
151#if !BOOST_FT_NO_CV_FUNC_SUPPORT
152    // Retry the type with a member pointer attached to detect cv functions
153    class a_class;
154
155    template<typename Base, typename T, typename L>
156    struct cv_func_base
157      : detail::retagged_if<Base,member_pointer_tag,function_tag>
158    {
159      typedef typename
160        mpl::remove
161          < typename Base::types
162          , typename detail::class_transform<a_class,L>::type>::type
163      types;
164    };
165
166    template<typename T, typename L>
167    struct components_impl<T*, L>
168      : mpl::if_
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
173        >::type
174    { };
175
176    template<typename T, typename L>
177    struct components_impl<T a_class::*, L>
178      : components_non_func_base
179    { };
180#else
181    template<typename T, typename L>
182    struct components_impl<T*, L>
183      : components_non_func_base
184    { }; 
185#endif
186
187    template<typename T, typename L>
188    struct components_impl<T* const, L> 
189      : components_impl<T*,L>
190    { };
191
192    template<typename T, typename L>
193    struct components_impl<T* volatile, L> 
194      : components_impl<T*,L>
195    { };
196
197    template<typename T, typename L>
198    struct components_impl<T* const volatile, L> 
199      : components_impl<T*,L>
200    { };
201
202    template<typename T, typename L>
203    struct components_impl<T const, L> 
204      : components_impl<T,L>
205    { };
206
207    template<typename T, typename L>
208    struct components_impl<T volatile, L> 
209      : components_impl<T,L>
210    { };
211
212    template<typename T, typename L>
213    struct components_impl<T const volatile, L> 
214      : components_impl<T,L>
215    { };
216
217
218    template<typename T, class C>
219    struct member_obj_ptr_result
220    { typedef T & type; };
221
222    template<typename T, class C>
223    struct member_obj_ptr_result<T, C const>
224    { typedef T const & type; };
225
226    template<typename T, class C>
227    struct member_obj_ptr_result<T, C volatile>
228    { typedef T volatile & type; };
229
230    template<typename T, class C>
231    struct member_obj_ptr_result<T, C const volatile>
232    { typedef T const volatile & type; };
233
234    template<typename T, class C>
235    struct member_obj_ptr_result<T &, C>
236    { typedef T & type; };
237
238    template<typename T, class C>
239    struct member_obj_ptr_result<T &, C const>
240    { typedef T & type; };
241
242    template<typename T, class C>
243    struct member_obj_ptr_result<T &, C volatile>
244    { typedef T & type; };
245
246    template<typename T, class C>
247    struct member_obj_ptr_result<T &, C const volatile>
248    { typedef T & type; };
249
250    template<typename T, class C, typename L>
251    struct member_obj_ptr_components
252      : member_object_pointer_base
253    {
254      typedef function_types::components<T C::*, L> type;
255      typedef components_mpl_sequence_tag tag;
256
257      typedef mpl::integral_c<std::size_t,1> function_arity;
258
259      typedef mpl::vector2< typename detail::member_obj_ptr_result<T,C>::type,
260          typename detail::class_transform<C,L>::type > types;
261    };
262
263#if !BOOST_WORKAROUND(__BORLANDC__, <= 0x565)
264#   define BOOST_FT_variations BOOST_FT_pointer|BOOST_FT_member_pointer
265
266    template<typename T, class C, typename L>
267    struct components_impl<T C::*, L>
268      : member_obj_ptr_components<T,C,L>
269    { };
270
271#else  
272#   define BOOST_FT_variations BOOST_FT_pointer
273
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> >
282    { };
283
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); };
298
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::*);
304
305    template<typename T> struct encode_mfp_cv
306    { 
307      BOOST_STATIC_CONSTANT(std::size_t, value = 
308          sizeof(detail::mfp_cv_tester((T)0L))); 
309    };
310
311    // Associate bits with the CV codes above.
312    template<std::size_t> struct cv_tag_mfp_impl;
313
314    template<typename T> struct cv_tag_mfp
315      : detail::cv_tag_mfp_impl
316        < ::boost::function_types::detail::encode_mfp_cv<T>::value >
317    { };
318
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        { };
323
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;
327
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 *> {};
333
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> 
339    { };
340
341    template<typename T, typename D, typename L> struct bcc_class_transform 
342      : bcc_class_transform_impl
343        < typename decode_cv
344          < T
345          , ::boost::function_types::detail::encode_mfp_cv<D>::value 
346          >::type
347        , L
348        > 
349    { };
350
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 
356    // parameter type. 
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;
361
362
363    template<typename Base, typename T, typename C, typename OrigT, typename L>
364    struct mfp_components<Base,T C::*,OrigT,L> 
365    {
366    private:
367      typedef typename mpl::front<typename Base::types>::type result_type;
368      typedef typename detail::bcc_class_transform<C,OrigT,L>::type class_type;
369
370      typedef mpl::vector2<result_type, class_type> result_and_class_type;
371
372      typedef typename 
373        mpl::advance
374        < typename mpl::begin<typename Base::types>::type
375        , typename mpl::if_
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> 
379          >::type
380        >::type
381      from;
382      typedef typename mpl::end<typename Base::types>::type to;
383
384      typedef mpl::iterator_range<from,to> param_types;
385
386      typedef mpl::joint_view< result_and_class_type, param_types> types_view;
387    public:
388
389      typedef typename 
390        mpl::reverse_copy<types_view, mpl::front_inserter< mpl::vector0<> > >::type 
391      types;
392
393      typedef typename 
394        function_types::tag< Base, detail::cv_tag_mfp<OrigT> >::bits 
395      bits;
396
397      typedef typename Base::mask mask;
398
399      typedef typename detail::classifier<OrigT>::function_arity function_arity;
400
401      typedef components_mpl_sequence_tag tag;
402    };
403
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
408      : mpl::if_
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>
413        >::type
414    { };
415
416#endif // end of BORLAND WORKAROUND
417
418#define BOOST_FT_al_path boost/function_types/detail/components_impl
419#include <boost/function_types/detail/pp_loop.hpp>
420
421  } } // namespace function_types::detail
422
423  BOOST_TT_AUX_TEMPLATE_ARITY_SPEC(2,function_types::components)
424
425} // namespace ::boost
426
427#include <boost/function_types/detail/components_as_mpl_sequence.hpp>
428#include <boost/function_types/detail/retag_default_cc.hpp>
429
430#endif
431