// (C) Copyright Tobias Schwinger // // Use modification and distribution are subject to the boost Software License, // Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). //------------------------------------------------------------------------------ #ifndef BOOST_FT_COMPONENTS_HPP_INCLUDED #define BOOST_FT_COMPONENTS_HPP_INCLUDED #include #include #include #include #include #include #include #include #include #if BOOST_WORKAROUND(__BORLANDC__, <= 0x565) # include # include # include # include # include # include # include # include # include # include # include # include # include #endif #ifndef BOOST_FT_NO_CV_FUNC_SUPPORT # include #endif #include #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION # if BOOST_FT_MAX_ARITY < 10 # include # elif BOOST_FT_MAX_ARITY < 20 # include # elif BOOST_FT_MAX_ARITY < 30 # include # elif BOOST_FT_MAX_ARITY < 40 # include # elif BOOST_FT_MAX_ARITY < 50 # include # endif #else # include #endif #include #include // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - namespace boost { namespace function_types { using mpl::placeholders::_; template< typename T, typename ClassTypeTransform = add_reference<_> > struct components; namespace detail { template struct components_impl; #if BOOST_WORKAROUND(__BORLANDC__, <= 0x565) template struct components_bcc; #endif } template struct components #if !BOOST_WORKAROUND(__BORLANDC__, <= 0x565) : detail::components_impl #else : detail::components_bcc::type,T, ClassTypeTransform> #endif { typedef components type; BOOST_MPL_AUX_LAMBDA_SUPPORT(2,components,(T,ClassTypeTransform)) }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - namespace detail { struct components_mpl_sequence_tag; struct components_non_func_base { typedef mpl::vector0<> types; typedef void function_arity; typedef detail::constant<0> bits; typedef detail::constant<0> mask; typedef components_mpl_sequence_tag tag; }; template < typename Components , typename IfTagged , typename ThenTag , typename DefaultBase = components_non_func_base > struct retagged_if : mpl::if_ < detail::represents_impl , detail::changed_tag , DefaultBase >::type { }; // We detect plain function types and function references as function // pointers by recursive instantiation of components_impl. // The third specialization of components_impl makes sure the recursion // terminates (when adding pointers). template struct components_impl : detail::retagged_if < detail::components_impl , pointer_tag, /* --> */ function_tag > { }; template struct components_impl : detail::retagged_if < detail::components_impl , pointer_tag, /* --> */ reference_tag > { }; #if !BOOST_FT_NO_CV_FUNC_SUPPORT // Retry the type with a member pointer attached to detect cv functions class a_class; template struct cv_func_base : detail::retagged_if { typedef typename mpl::remove < typename Base::types , typename detail::class_transform::type>::type types; }; template struct components_impl : mpl::if_ < detail::represents_impl< detail::components_impl , member_pointer_tag > , detail::cv_func_base< detail::components_impl, T, L> , components_non_func_base >::type { }; template struct components_impl : components_non_func_base { }; #else template struct components_impl : components_non_func_base { }; #endif template struct components_impl : components_impl { }; template struct components_impl : components_impl { }; template struct components_impl : components_impl { }; template struct components_impl : components_impl { }; template struct components_impl : components_impl { }; template struct components_impl : components_impl { }; template struct member_obj_ptr_result { typedef T & type; }; template struct member_obj_ptr_result { typedef T const & type; }; template struct member_obj_ptr_result { typedef T volatile & type; }; template struct member_obj_ptr_result { typedef T const volatile & type; }; template struct member_obj_ptr_result { typedef T & type; }; template struct member_obj_ptr_result { typedef T & type; }; template struct member_obj_ptr_result { typedef T & type; }; template struct member_obj_ptr_result { typedef T & type; }; template struct member_obj_ptr_components : member_object_pointer_base { typedef function_types::components type; typedef components_mpl_sequence_tag tag; typedef mpl::integral_c function_arity; typedef mpl::vector2< typename detail::member_obj_ptr_result::type, typename detail::class_transform::type > types; }; #if !BOOST_WORKAROUND(__BORLANDC__, <= 0x565) # define BOOST_FT_variations BOOST_FT_pointer|BOOST_FT_member_pointer template struct components_impl : member_obj_ptr_components { }; #else # define BOOST_FT_variations BOOST_FT_pointer // This workaround removes the member pointer from the type to allow // detection of member function pointers with BCC. template struct components_impl : detail::retagged_if < detail::components_impl::type *, L> , pointer_tag, /* --> */ member_function_pointer_tag , member_obj_ptr_components > { }; // BCC lets us test the cv-qualification of a function type by template // partial specialization - so we use this bug feature to find out the // member function's cv-qualification (unfortunately there are some // invisible modifiers that impose some limitations on these types even if // we remove the qualifiers, So we cannot exploit the same bug to make the // library work for cv-qualified function types). template struct encode_cv { typedef char (& type)[1]; BOOST_STATIC_CONSTANT(std::size_t, value = 1); }; template struct encode_cv { typedef char (& type)[2]; BOOST_STATIC_CONSTANT(std::size_t, value = 2); }; template struct encode_cv { typedef char (& type)[3]; BOOST_STATIC_CONSTANT(std::size_t, value = 3); }; template struct encode_cv { typedef char (& type)[4]; BOOST_STATIC_CONSTANT(std::size_t, value = 4); }; // For member function pointers we have to use a function template (partial // template specialization for a member pointer drops the cv qualification // of the function type). template typename encode_cv::type mfp_cv_tester(T C::*); template struct encode_mfp_cv { BOOST_STATIC_CONSTANT(std::size_t, value = sizeof(detail::mfp_cv_tester((T)0L))); }; // Associate bits with the CV codes above. template struct cv_tag_mfp_impl; template struct cv_tag_mfp : detail::cv_tag_mfp_impl < ::boost::function_types::detail::encode_mfp_cv::value > { }; template<> struct cv_tag_mfp_impl<1> : non_cv { }; template<> struct cv_tag_mfp_impl<2> : const_non_volatile { }; template<> struct cv_tag_mfp_impl<3> : volatile_non_const { }; template<> struct cv_tag_mfp_impl<4> : cv_qualified { }; // Metafunction to decode the cv code and apply it to a type. // We add a pointer, because otherwise cv-qualifiers won't stick (another bug). template struct decode_cv; template struct decode_cv : mpl::identity {}; template struct decode_cv : mpl::identity {}; template struct decode_cv : mpl::identity {}; template struct decode_cv : mpl::identity {}; // The class type transformation comes after adding cv-qualifiers. We have // wrap it to remove the pointer added in decode_cv_impl. template struct bcc_class_transform_impl; template struct bcc_class_transform_impl : class_transform { }; template struct bcc_class_transform : bcc_class_transform_impl < typename decode_cv < T , ::boost::function_types::detail::encode_mfp_cv::value >::type , L > { }; // After extracting the member pointee from the type the class type is still // in the type (somewhere -- you won't see with RTTI, that is) and that type // is flagged unusable and *not* identical to the nonmember function type. // We can, however, decompose this type via components_impl but surprisingly // a pointer to the const qualified class type pops up again as the first // parameter type. // We have to replace this type with the properly cv-qualified and // transformed class type, integrate the cv qualification into the bits. template struct mfp_components; template struct mfp_components { private: typedef typename mpl::front::type result_type; typedef typename detail::bcc_class_transform::type class_type; typedef mpl::vector2 result_and_class_type; typedef typename mpl::advance < typename mpl::begin::type , typename mpl::if_ < mpl::equal_to< typename detail::classifier::function_arity , typename Base::function_arity > , mpl::integral_c , mpl::integral_c >::type >::type from; typedef typename mpl::end::type to; typedef mpl::iterator_range param_types; typedef mpl::joint_view< result_and_class_type, param_types> types_view; public: typedef typename mpl::reverse_copy > >::type types; typedef typename function_types::tag< Base, detail::cv_tag_mfp >::bits bits; typedef typename Base::mask mask; typedef typename detail::classifier::function_arity function_arity; typedef components_mpl_sequence_tag tag; }; // Now put it all together: detect cv-qualification of function types and do // the weird transformations above for member function pointers. template struct components_bcc : mpl::if_ < detail::represents_impl< detail::components_impl , member_function_pointer_tag> , detail::mfp_components,T,OrigT,L> , detail::components_impl >::type { }; #endif // end of BORLAND WORKAROUND #define BOOST_FT_al_path boost/function_types/detail/components_impl #include } } // namespace function_types::detail BOOST_TT_AUX_TEMPLATE_ARITY_SPEC(2,function_types::components) } // namespace ::boost #include #include #endif