components.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. // (C) Copyright Tobias Schwinger
  2. //
  3. // Use modification and distribution are subject to the boost Software License,
  4. // Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt).
  5. //------------------------------------------------------------------------------
  6. #ifndef BOOST_FT_COMPONENTS_HPP_INCLUDED
  7. #define BOOST_FT_COMPONENTS_HPP_INCLUDED
  8. #include <cstddef>
  9. #include <boost/config.hpp>
  10. #include <boost/detail/workaround.hpp>
  11. #include <boost/mpl/aux_/lambda_support.hpp>
  12. #include <boost/type_traits/integral_constant.hpp>
  13. #include <boost/mpl/if.hpp>
  14. #include <boost/mpl/integral_c.hpp>
  15. #include <boost/mpl/vector/vector0.hpp>
  16. #if BOOST_WORKAROUND(__BORLANDC__, <= 0x565)
  17. # include <boost/type_traits/remove_cv.hpp>
  18. # include <boost/mpl/identity.hpp>
  19. # include <boost/mpl/bitand.hpp>
  20. # include <boost/mpl/vector/vector10.hpp>
  21. # include <boost/mpl/front.hpp>
  22. # include <boost/mpl/begin.hpp>
  23. # include <boost/mpl/advance.hpp>
  24. # include <boost/mpl/iterator_range.hpp>
  25. # include <boost/mpl/joint_view.hpp>
  26. # include <boost/mpl/equal_to.hpp>
  27. # include <boost/mpl/copy.hpp>
  28. # include <boost/mpl/front_inserter.hpp>
  29. # include <boost/function_types/detail/classifier.hpp>
  30. #endif
  31. #ifndef BOOST_FT_NO_CV_FUNC_SUPPORT
  32. # include <boost/mpl/remove.hpp>
  33. #endif
  34. #include <boost/function_types/config/config.hpp>
  35. # if BOOST_FT_MAX_ARITY < 10
  36. # include <boost/mpl/vector/vector10.hpp>
  37. # elif BOOST_FT_MAX_ARITY < 20
  38. # include <boost/mpl/vector/vector20.hpp>
  39. # elif BOOST_FT_MAX_ARITY < 30
  40. # include <boost/mpl/vector/vector30.hpp>
  41. # elif BOOST_FT_MAX_ARITY < 40
  42. # include <boost/mpl/vector/vector40.hpp>
  43. # elif BOOST_FT_MAX_ARITY < 50
  44. # include <boost/mpl/vector/vector50.hpp>
  45. # endif
  46. #include <boost/function_types/detail/class_transform.hpp>
  47. #include <boost/function_types/property_tags.hpp>
  48. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  49. namespace boost
  50. {
  51. namespace function_types
  52. {
  53. using mpl::placeholders::_;
  54. template< typename T, typename ClassTypeTransform = add_reference<_> >
  55. struct components;
  56. namespace detail
  57. {
  58. template<typename T, typename L> struct components_impl;
  59. #if BOOST_WORKAROUND(__BORLANDC__, <= 0x565)
  60. template<typename T, typename OrigT, typename L> struct components_bcc;
  61. #endif
  62. }
  63. template<typename T, typename ClassTypeTransform>
  64. struct components
  65. #if !BOOST_WORKAROUND(__BORLANDC__, <= 0x565)
  66. : detail::components_impl<T, ClassTypeTransform>
  67. #else
  68. : detail::components_bcc<typename remove_cv<T>::type,T,
  69. ClassTypeTransform>
  70. #endif
  71. {
  72. typedef components<T,ClassTypeTransform> type;
  73. BOOST_MPL_AUX_LAMBDA_SUPPORT(2,components,(T,ClassTypeTransform))
  74. };
  75. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  76. namespace detail {
  77. struct components_mpl_sequence_tag;
  78. struct components_non_func_base
  79. {
  80. typedef mpl::vector0<> types;
  81. typedef void function_arity;
  82. typedef detail::constant<0> bits;
  83. typedef detail::constant<0> mask;
  84. typedef components_mpl_sequence_tag tag;
  85. };
  86. template
  87. < typename Components
  88. , typename IfTagged
  89. , typename ThenTag
  90. , typename DefaultBase = components_non_func_base
  91. >
  92. struct retagged_if
  93. : mpl::if_
  94. < detail::represents_impl<Components, IfTagged>
  95. , detail::changed_tag<Components,IfTagged,ThenTag>
  96. , DefaultBase
  97. >::type
  98. { };
  99. // We detect plain function types and function references as function
  100. // pointers by recursive instantiation of components_impl.
  101. // The third specialization of components_impl makes sure the recursion
  102. // terminates (when adding pointers).
  103. template<typename T, typename L>
  104. struct components_impl
  105. : detail::retagged_if
  106. < detail::components_impl<T*,L>
  107. , pointer_tag, /* --> */ function_tag >
  108. { };
  109. template<typename T, typename L>
  110. struct components_impl<T&, L>
  111. : detail::retagged_if
  112. < detail::components_impl<T*,L>
  113. , pointer_tag, /* --> */ reference_tag >
  114. { };
  115. #if !BOOST_FT_NO_CV_FUNC_SUPPORT
  116. // Retry the type with a member pointer attached to detect cv functions
  117. class a_class;
  118. template<typename Base, typename T, typename L>
  119. struct cv_func_base
  120. : detail::retagged_if<Base,member_pointer_tag,function_tag>
  121. {
  122. typedef typename
  123. mpl::remove
  124. < typename Base::types
  125. , typename detail::class_transform<a_class,L>::type>::type
  126. types;
  127. };
  128. template<typename T, typename L>
  129. struct components_impl<T*, L>
  130. : mpl::if_
  131. < detail::represents_impl< detail::components_impl<T a_class::*, L>
  132. , member_pointer_tag >
  133. , detail::cv_func_base< detail::components_impl<T a_class::*, L>, T, L>
  134. , components_non_func_base
  135. >::type
  136. { };
  137. template<typename T, typename L>
  138. struct components_impl<T a_class::*, L>
  139. : components_non_func_base
  140. { };
  141. #else
  142. template<typename T, typename L>
  143. struct components_impl<T*, L>
  144. : components_non_func_base
  145. { };
  146. #endif
  147. template<typename T, typename L>
  148. struct components_impl<T* const, L>
  149. : components_impl<T*,L>
  150. { };
  151. template<typename T, typename L>
  152. struct components_impl<T* volatile, L>
  153. : components_impl<T*,L>
  154. { };
  155. template<typename T, typename L>
  156. struct components_impl<T* const volatile, L>
  157. : components_impl<T*,L>
  158. { };
  159. template<typename T, typename L>
  160. struct components_impl<T const, L>
  161. : components_impl<T,L>
  162. { };
  163. template<typename T, typename L>
  164. struct components_impl<T volatile, L>
  165. : components_impl<T,L>
  166. { };
  167. template<typename T, typename L>
  168. struct components_impl<T const volatile, L>
  169. : components_impl<T,L>
  170. { };
  171. template<typename T, class C>
  172. struct member_obj_ptr_result
  173. { typedef T & type; };
  174. template<typename T, class C>
  175. struct member_obj_ptr_result<T, C const>
  176. { typedef T const & type; };
  177. template<typename T, class C>
  178. struct member_obj_ptr_result<T, C volatile>
  179. { typedef T volatile & type; };
  180. template<typename T, class C>
  181. struct member_obj_ptr_result<T, C const volatile>
  182. { typedef T const volatile & type; };
  183. template<typename T, class C>
  184. struct member_obj_ptr_result<T &, C>
  185. { typedef T & type; };
  186. template<typename T, class C>
  187. struct member_obj_ptr_result<T &, C const>
  188. { typedef T & type; };
  189. template<typename T, class C>
  190. struct member_obj_ptr_result<T &, C volatile>
  191. { typedef T & type; };
  192. template<typename T, class C>
  193. struct member_obj_ptr_result<T &, C const volatile>
  194. { typedef T & type; };
  195. template<typename T, class C, typename L>
  196. struct member_obj_ptr_components
  197. : member_object_pointer_base
  198. {
  199. typedef function_types::components<T C::*, L> type;
  200. typedef components_mpl_sequence_tag tag;
  201. typedef mpl::integral_c<std::size_t,1> function_arity;
  202. typedef mpl::vector2< typename detail::member_obj_ptr_result<T,C>::type,
  203. typename detail::class_transform<C,L>::type > types;
  204. };
  205. #if !BOOST_WORKAROUND(__BORLANDC__, <= 0x565)
  206. # define BOOST_FT_variations BOOST_FT_pointer|BOOST_FT_member_pointer
  207. template<typename T, class C, typename L>
  208. struct components_impl<T C::*, L>
  209. : member_obj_ptr_components<T,C,L>
  210. { };
  211. #else
  212. # define BOOST_FT_variations BOOST_FT_pointer
  213. // This workaround removes the member pointer from the type to allow
  214. // detection of member function pointers with BCC.
  215. template<typename T, typename C, typename L>
  216. struct components_impl<T C::*, L>
  217. : detail::retagged_if
  218. < detail::components_impl<typename boost::remove_cv<T>::type *, L>
  219. , pointer_tag, /* --> */ member_function_pointer_tag
  220. , member_obj_ptr_components<T,C,L> >
  221. { };
  222. // BCC lets us test the cv-qualification of a function type by template
  223. // partial specialization - so we use this bug feature to find out the
  224. // member function's cv-qualification (unfortunately there are some
  225. // invisible modifiers that impose some limitations on these types even if
  226. // we remove the qualifiers, So we cannot exploit the same bug to make the
  227. // library work for cv-qualified function types).
  228. template<typename T> struct encode_cv
  229. { typedef char (& type)[1]; BOOST_STATIC_CONSTANT(std::size_t, value = 1); };
  230. template<typename T> struct encode_cv<T const *>
  231. { typedef char (& type)[2]; BOOST_STATIC_CONSTANT(std::size_t, value = 2); };
  232. template<typename T> struct encode_cv<T volatile *>
  233. { typedef char (& type)[3]; BOOST_STATIC_CONSTANT(std::size_t, value = 3); };
  234. template<typename T> struct encode_cv<T const volatile *>
  235. { typedef char (& type)[4]; BOOST_STATIC_CONSTANT(std::size_t, value = 4); };
  236. // For member function pointers we have to use a function template (partial
  237. // template specialization for a member pointer drops the cv qualification
  238. // of the function type).
  239. template<typename T, typename C>
  240. typename encode_cv<T *>::type mfp_cv_tester(T C::*);
  241. template<typename T> struct encode_mfp_cv
  242. {
  243. BOOST_STATIC_CONSTANT(std::size_t, value =
  244. sizeof(detail::mfp_cv_tester((T)0L)));
  245. };
  246. // Associate bits with the CV codes above.
  247. template<std::size_t> struct cv_tag_mfp_impl;
  248. template<typename T> struct cv_tag_mfp
  249. : detail::cv_tag_mfp_impl
  250. < ::boost::function_types::detail::encode_mfp_cv<T>::value >
  251. { };
  252. template<> struct cv_tag_mfp_impl<1> : non_cv { };
  253. template<> struct cv_tag_mfp_impl<2> : const_non_volatile { };
  254. template<> struct cv_tag_mfp_impl<3> : volatile_non_const { };
  255. template<> struct cv_tag_mfp_impl<4> : cv_qualified { };
  256. // Metafunction to decode the cv code and apply it to a type.
  257. // We add a pointer, because otherwise cv-qualifiers won't stick (another bug).
  258. template<typename T, std::size_t CV> struct decode_cv;
  259. template<typename T> struct decode_cv<T,1> : mpl::identity<T *> {};
  260. template<typename T> struct decode_cv<T,2> : mpl::identity<T const *> {};
  261. template<typename T> struct decode_cv<T,3> : mpl::identity<T volatile *> {};
  262. template<typename T> struct decode_cv<T,4>
  263. : mpl::identity<T const volatile *> {};
  264. // The class type transformation comes after adding cv-qualifiers. We have
  265. // wrap it to remove the pointer added in decode_cv_impl.
  266. template<typename T, typename L> struct bcc_class_transform_impl;
  267. template<typename T, typename L> struct bcc_class_transform_impl<T *, L>
  268. : class_transform<T,L>
  269. { };
  270. template<typename T, typename D, typename L> struct bcc_class_transform
  271. : bcc_class_transform_impl
  272. < typename decode_cv
  273. < T
  274. , ::boost::function_types::detail::encode_mfp_cv<D>::value
  275. >::type
  276. , L
  277. >
  278. { };
  279. // After extracting the member pointee from the type the class type is still
  280. // in the type (somewhere -- you won't see with RTTI, that is) and that type
  281. // is flagged unusable and *not* identical to the nonmember function type.
  282. // We can, however, decompose this type via components_impl but surprisingly
  283. // a pointer to the const qualified class type pops up again as the first
  284. // parameter type.
  285. // We have to replace this type with the properly cv-qualified and
  286. // transformed class type, integrate the cv qualification into the bits.
  287. template<typename Base, typename MFP, typename OrigT, typename L>
  288. struct mfp_components;
  289. template<typename Base, typename T, typename C, typename OrigT, typename L>
  290. struct mfp_components<Base,T C::*,OrigT,L>
  291. {
  292. private:
  293. typedef typename mpl::front<typename Base::types>::type result_type;
  294. typedef typename detail::bcc_class_transform<C,OrigT,L>::type class_type;
  295. typedef mpl::vector2<result_type, class_type> result_and_class_type;
  296. typedef typename
  297. mpl::advance
  298. < typename mpl::begin<typename Base::types>::type
  299. , typename mpl::if_
  300. < mpl::equal_to< typename detail::classifier<OrigT>::function_arity
  301. , typename Base::function_arity >
  302. , mpl::integral_c<int,2> , mpl::integral_c<int,1>
  303. >::type
  304. >::type
  305. from;
  306. typedef typename mpl::end<typename Base::types>::type to;
  307. typedef mpl::iterator_range<from,to> param_types;
  308. typedef mpl::joint_view< result_and_class_type, param_types> types_view;
  309. public:
  310. typedef typename
  311. mpl::reverse_copy<types_view, mpl::front_inserter< mpl::vector0<> > >::type
  312. types;
  313. typedef typename
  314. function_types::tag< Base, detail::cv_tag_mfp<OrigT> >::bits
  315. bits;
  316. typedef typename Base::mask mask;
  317. typedef typename detail::classifier<OrigT>::function_arity function_arity;
  318. typedef components_mpl_sequence_tag tag;
  319. };
  320. // Now put it all together: detect cv-qualification of function types and do
  321. // the weird transformations above for member function pointers.
  322. template<typename T, typename OrigT, typename L>
  323. struct components_bcc
  324. : mpl::if_
  325. < detail::represents_impl< detail::components_impl<T,L>
  326. , member_function_pointer_tag>
  327. , detail::mfp_components<detail::components_impl<T,L>,T,OrigT,L>
  328. , detail::components_impl<T,L>
  329. >::type
  330. { };
  331. #endif // end of BORLAND WORKAROUND
  332. #define BOOST_FT_al_path boost/function_types/detail/components_impl
  333. #include <boost/function_types/detail/pp_loop.hpp>
  334. } } // namespace function_types::detail
  335. } // namespace ::boost
  336. #include <boost/function_types/detail/components_as_mpl_sequence.hpp>
  337. #include <boost/function_types/detail/retag_default_cc.hpp>
  338. #endif