Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:31:06

0001 
0002 // (C) Copyright Tobias Schwinger
0003 //
0004 // Use modification and distribution are subject to the boost Software License,
0005 // Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt).
0006 
0007 //------------------------------------------------------------------------------
0008 
0009 #ifndef BOOST_FT_COMPONENTS_HPP_INCLUDED
0010 #define BOOST_FT_COMPONENTS_HPP_INCLUDED
0011 
0012 #include <cstddef>
0013 
0014 #include <boost/config.hpp>
0015 
0016 #include <boost/detail/workaround.hpp>
0017 #include <boost/mpl/aux_/lambda_support.hpp>
0018 
0019 #include <boost/type_traits/integral_constant.hpp>
0020 
0021 #include <boost/mpl/if.hpp>
0022 #include <boost/mpl/integral_c.hpp>
0023 #include <boost/mpl/vector/vector0.hpp>
0024 
0025 #if BOOST_WORKAROUND(BOOST_BORLANDC, <= 0x565)
0026 #   include <boost/type_traits/remove_cv.hpp>
0027 
0028 #   include <boost/mpl/identity.hpp>
0029 #   include <boost/mpl/bitand.hpp>
0030 #   include <boost/mpl/vector/vector10.hpp>
0031 #   include <boost/mpl/front.hpp>
0032 #   include <boost/mpl/begin.hpp>
0033 #   include <boost/mpl/advance.hpp>
0034 #   include <boost/mpl/iterator_range.hpp>
0035 #   include <boost/mpl/joint_view.hpp>
0036 #   include <boost/mpl/equal_to.hpp>
0037 #   include <boost/mpl/copy.hpp>
0038 #   include <boost/mpl/front_inserter.hpp>
0039 
0040 #   include <boost/function_types/detail/classifier.hpp>
0041 #endif
0042 
0043 #ifndef BOOST_FT_NO_CV_FUNC_SUPPORT
0044 #   include <boost/mpl/remove.hpp>
0045 #endif
0046 
0047 #include <boost/function_types/config/config.hpp>
0048 
0049 #   if   BOOST_FT_MAX_ARITY < 10
0050 #     include <boost/mpl/vector/vector10.hpp>
0051 #   elif BOOST_FT_MAX_ARITY < 20
0052 #     include <boost/mpl/vector/vector20.hpp>
0053 #   elif BOOST_FT_MAX_ARITY < 30
0054 #     include <boost/mpl/vector/vector30.hpp>
0055 #   elif BOOST_FT_MAX_ARITY < 40
0056 #     include <boost/mpl/vector/vector40.hpp>
0057 #   elif BOOST_FT_MAX_ARITY < 50
0058 #     include <boost/mpl/vector/vector50.hpp>
0059 #   endif
0060 
0061 #include <boost/function_types/detail/class_transform.hpp>
0062 #include <boost/function_types/property_tags.hpp>
0063 
0064 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
0065 
0066 namespace boost 
0067 { 
0068   namespace function_types 
0069   {
0070 
0071     using mpl::placeholders::_;
0072 
0073     template< typename T, typename ClassTypeTransform = add_reference<_> > 
0074     struct components;
0075 
0076     namespace detail 
0077     {
0078       template<typename T, typename L> struct components_impl;
0079 #if BOOST_WORKAROUND(BOOST_BORLANDC, <= 0x565)
0080       template<typename T, typename OrigT, typename L> struct components_bcc;
0081 #endif
0082     }
0083 
0084     template<typename T, typename ClassTypeTransform> 
0085     struct components
0086 #if !BOOST_WORKAROUND(BOOST_BORLANDC, <= 0x565)
0087       : detail::components_impl<T, ClassTypeTransform>
0088 #else
0089       : detail::components_bcc<typename remove_cv<T>::type,T,
0090             ClassTypeTransform>
0091 #endif
0092     { 
0093       typedef components<T,ClassTypeTransform> type;
0094 
0095       BOOST_MPL_AUX_LAMBDA_SUPPORT(2,components,(T,ClassTypeTransform))
0096     };
0097 
0098 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
0099 
0100   namespace detail {
0101 
0102     struct components_mpl_sequence_tag; 
0103 
0104     struct components_non_func_base
0105     {
0106       typedef mpl::vector0<> types;
0107       typedef void function_arity;
0108 
0109       typedef detail::constant<0> bits;
0110       typedef detail::constant<0> mask;
0111 
0112       typedef components_mpl_sequence_tag tag;
0113     };
0114 
0115     template
0116     < typename Components
0117     , typename IfTagged
0118     , typename ThenTag
0119     , typename DefaultBase = components_non_func_base
0120     >
0121     struct retagged_if
0122       : mpl::if_
0123         < detail::represents_impl<Components, IfTagged>
0124         , detail::changed_tag<Components,IfTagged,ThenTag>
0125         , DefaultBase
0126         >::type
0127     { };
0128 
0129     // We detect plain function types and function references as function 
0130     // pointers by recursive instantiation of components_impl. 
0131     // The third specialization of components_impl makes sure the recursion 
0132     // terminates (when adding pointers).
0133     template<typename T, typename L>
0134     struct components_impl
0135       : detail::retagged_if
0136         < detail::components_impl<T*,L>
0137         , pointer_tag, /* --> */ function_tag >
0138     { };
0139     template<typename T, typename L>
0140     struct components_impl<T&, L>
0141       : detail::retagged_if
0142         < detail::components_impl<T*,L>
0143         , pointer_tag, /* --> */ reference_tag >
0144     { };
0145 
0146 #if !BOOST_FT_NO_CV_FUNC_SUPPORT
0147     // Retry the type with a member pointer attached to detect cv functions
0148     class a_class;
0149 
0150     template<typename Base, typename T, typename L>
0151     struct cv_func_base
0152       : detail::retagged_if<Base,member_pointer_tag,function_tag>
0153     {
0154       typedef typename
0155         mpl::remove
0156           < typename Base::types
0157           , typename detail::class_transform<a_class,L>::type>::type
0158       types;
0159     };
0160 
0161     template<typename T, typename L>
0162     struct components_impl<T*, L>
0163       : mpl::if_
0164         < detail::represents_impl< detail::components_impl<T a_class::*, L>
0165                                  , member_pointer_tag >
0166         , detail::cv_func_base< detail::components_impl<T a_class::*, L>, T, L>
0167         , components_non_func_base
0168         >::type
0169     { };
0170 
0171     template<typename T, typename L>
0172     struct components_impl<T a_class::*, L>
0173       : components_non_func_base
0174     { };
0175 #else
0176     template<typename T, typename L>
0177     struct components_impl<T*, L>
0178       : components_non_func_base
0179     { }; 
0180 #endif
0181 
0182     template<typename T, typename L>
0183     struct components_impl<T* const, L> 
0184       : components_impl<T*,L>
0185     { };
0186 
0187     template<typename T, typename L>
0188     struct components_impl<T* volatile, L> 
0189       : components_impl<T*,L>
0190     { };
0191 
0192     template<typename T, typename L>
0193     struct components_impl<T* const volatile, L> 
0194       : components_impl<T*,L>
0195     { };
0196 
0197     template<typename T, typename L>
0198     struct components_impl<T const, L> 
0199       : components_impl<T,L>
0200     { };
0201 
0202     template<typename T, typename L>
0203     struct components_impl<T volatile, L> 
0204       : components_impl<T,L>
0205     { };
0206 
0207     template<typename T, typename L>
0208     struct components_impl<T const volatile, L> 
0209       : components_impl<T,L>
0210     { };
0211 
0212 
0213     template<typename T, class C>
0214     struct member_obj_ptr_result
0215     { typedef T & type; };
0216 
0217     template<typename T, class C>
0218     struct member_obj_ptr_result<T, C const>
0219     { typedef T const & type; };
0220 
0221     template<typename T, class C>
0222     struct member_obj_ptr_result<T, C volatile>
0223     { typedef T volatile & type; };
0224 
0225     template<typename T, class C>
0226     struct member_obj_ptr_result<T, C const volatile>
0227     { typedef T const volatile & type; };
0228 
0229     template<typename T, class C>
0230     struct member_obj_ptr_result<T &, C>
0231     { typedef T & type; };
0232 
0233     template<typename T, class C>
0234     struct member_obj_ptr_result<T &, C const>
0235     { typedef T & type; };
0236 
0237     template<typename T, class C>
0238     struct member_obj_ptr_result<T &, C volatile>
0239     { typedef T & type; };
0240 
0241     template<typename T, class C>
0242     struct member_obj_ptr_result<T &, C const volatile>
0243     { typedef T & type; };
0244 
0245     template<typename T, class C, typename L>
0246     struct member_obj_ptr_components
0247       : member_object_pointer_base
0248     {
0249       typedef function_types::components<T C::*, L> type;
0250       typedef components_mpl_sequence_tag tag;
0251 
0252       typedef mpl::integral_c<std::size_t,1> function_arity;
0253 
0254       typedef mpl::vector2< typename detail::member_obj_ptr_result<T,C>::type,
0255           typename detail::class_transform<C,L>::type > types;
0256     };
0257 
0258 #if !BOOST_WORKAROUND(BOOST_BORLANDC, <= 0x565)
0259 #   define BOOST_FT_variations BOOST_FT_pointer|BOOST_FT_member_pointer
0260 
0261     template<typename T, class C, typename L>
0262     struct components_impl<T C::*, L>
0263       : member_obj_ptr_components<T,C,L>
0264     { };
0265 
0266 #else  
0267 #   define BOOST_FT_variations BOOST_FT_pointer
0268 
0269     // This workaround removes the member pointer from the type to allow 
0270     // detection of member function pointers with BCC. 
0271     template<typename T, typename C, typename L>
0272     struct components_impl<T C::*, L>
0273       : detail::retagged_if
0274         < detail::components_impl<typename boost::remove_cv<T>::type *, L>
0275         , pointer_tag, /* --> */ member_function_pointer_tag
0276         , member_obj_ptr_components<T,C,L> >
0277     { };
0278 
0279     // BCC lets us test the cv-qualification of a function type by template 
0280     // partial specialization - so we use this bug feature to find out the 
0281     // member function's cv-qualification (unfortunately there are some 
0282     // invisible modifiers that impose some limitations on these types even if
0283     // we remove the qualifiers, So we cannot exploit the same bug to make the 
0284     // library work for cv-qualified function types).
0285     template<typename T> struct encode_cv
0286     { typedef char (& type)[1]; BOOST_STATIC_CONSTANT(std::size_t, value = 1); };
0287     template<typename T> struct encode_cv<T const *>
0288     { typedef char (& type)[2]; BOOST_STATIC_CONSTANT(std::size_t, value = 2); };
0289     template<typename T> struct encode_cv<T volatile *>
0290     { typedef char (& type)[3]; BOOST_STATIC_CONSTANT(std::size_t, value = 3); };
0291     template<typename T> struct encode_cv<T const volatile *> 
0292     { typedef char (& type)[4]; BOOST_STATIC_CONSTANT(std::size_t, value = 4); };
0293 
0294     // For member function pointers we have to use a function template (partial
0295     // template specialization for a member pointer drops the cv qualification 
0296     // of the function type).
0297     template<typename T, typename C>
0298     typename encode_cv<T *>::type mfp_cv_tester(T C::*);
0299 
0300     template<typename T> struct encode_mfp_cv
0301     { 
0302       BOOST_STATIC_CONSTANT(std::size_t, value = 
0303           sizeof(detail::mfp_cv_tester((T)0L))); 
0304     };
0305 
0306     // Associate bits with the CV codes above.
0307     template<std::size_t> struct cv_tag_mfp_impl;
0308 
0309     template<typename T> struct cv_tag_mfp
0310       : detail::cv_tag_mfp_impl
0311         < ::boost::function_types::detail::encode_mfp_cv<T>::value >
0312     { };
0313 
0314     template<> struct cv_tag_mfp_impl<1> : non_cv              { };
0315     template<> struct cv_tag_mfp_impl<2> : const_non_volatile  { };
0316     template<> struct cv_tag_mfp_impl<3> : volatile_non_const  { };
0317     template<> struct cv_tag_mfp_impl<4> : cv_qualified        { };
0318 
0319     // Metafunction to decode the cv code and apply it to a type.
0320     // We add a pointer, because otherwise cv-qualifiers won't stick (another bug).
0321     template<typename T, std::size_t CV> struct decode_cv;
0322 
0323     template<typename T> struct decode_cv<T,1> : mpl::identity<T *>          {};
0324     template<typename T> struct decode_cv<T,2> : mpl::identity<T const *>    {};
0325     template<typename T> struct decode_cv<T,3> : mpl::identity<T volatile *> {};
0326     template<typename T> struct decode_cv<T,4> 
0327                                          : mpl::identity<T const volatile *> {};
0328 
0329     // The class type transformation comes after adding cv-qualifiers. We have
0330     // wrap it to remove the pointer added in decode_cv_impl.
0331     template<typename T, typename L> struct bcc_class_transform_impl;
0332     template<typename T, typename L> struct bcc_class_transform_impl<T *, L>
0333       : class_transform<T,L> 
0334     { };
0335 
0336     template<typename T, typename D, typename L> struct bcc_class_transform 
0337       : bcc_class_transform_impl
0338         < typename decode_cv
0339           < T
0340           , ::boost::function_types::detail::encode_mfp_cv<D>::value 
0341           >::type
0342         , L
0343         > 
0344     { };
0345 
0346     // After extracting the member pointee from the type the class type is still
0347     // in the type (somewhere -- you won't see with RTTI, that is) and that type
0348     // is flagged unusable and *not* identical to the nonmember function type.
0349     // We can, however, decompose this type via components_impl but surprisingly
0350     // a pointer to the const qualified class type pops up again as the first 
0351     // parameter type. 
0352     // We have to replace this type with the properly cv-qualified and 
0353     // transformed class type, integrate the cv qualification into the bits.
0354     template<typename Base, typename MFP, typename OrigT, typename L>
0355     struct mfp_components;
0356 
0357 
0358     template<typename Base, typename T, typename C, typename OrigT, typename L>
0359     struct mfp_components<Base,T C::*,OrigT,L> 
0360     {
0361     private:
0362       typedef typename mpl::front<typename Base::types>::type result_type;
0363       typedef typename detail::bcc_class_transform<C,OrigT,L>::type class_type;
0364 
0365       typedef mpl::vector2<result_type, class_type> result_and_class_type;
0366 
0367       typedef typename 
0368         mpl::advance
0369         < typename mpl::begin<typename Base::types>::type
0370         , typename mpl::if_
0371           < mpl::equal_to< typename detail::classifier<OrigT>::function_arity
0372                          , typename Base::function_arity >
0373           , mpl::integral_c<int,2> , mpl::integral_c<int,1> 
0374           >::type
0375         >::type
0376       from;
0377       typedef typename mpl::end<typename Base::types>::type to;
0378 
0379       typedef mpl::iterator_range<from,to> param_types;
0380 
0381       typedef mpl::joint_view< result_and_class_type, param_types> types_view;
0382     public:
0383 
0384       typedef typename 
0385         mpl::reverse_copy<types_view, mpl::front_inserter< mpl::vector0<> > >::type 
0386       types;
0387 
0388       typedef typename 
0389         function_types::tag< Base, detail::cv_tag_mfp<OrigT> >::bits 
0390       bits;
0391 
0392       typedef typename Base::mask mask;
0393 
0394       typedef typename detail::classifier<OrigT>::function_arity function_arity;
0395 
0396       typedef components_mpl_sequence_tag tag;
0397     };
0398 
0399     // Now put it all together: detect cv-qualification of function types and do
0400     // the weird transformations above for member function pointers.
0401     template<typename T, typename OrigT, typename L>
0402     struct components_bcc
0403       : mpl::if_
0404         < detail::represents_impl< detail::components_impl<T,L>
0405                                  , member_function_pointer_tag>
0406         , detail::mfp_components<detail::components_impl<T,L>,T,OrigT,L>
0407         , detail::components_impl<T,L>
0408         >::type
0409     { };
0410 
0411 #endif // end of BORLAND WORKAROUND
0412 
0413 #define BOOST_FT_al_path boost/function_types/detail/components_impl
0414 #include <boost/function_types/detail/pp_loop.hpp>
0415 
0416   } } // namespace function_types::detail
0417 
0418 } // namespace ::boost
0419 
0420 #include <boost/function_types/detail/components_as_mpl_sequence.hpp>
0421 #include <boost/function_types/detail/retag_default_cc.hpp>
0422 
0423 #endif
0424