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