/Src/Dependencies/Boost/boost/proto/detail/decltype.hpp

http://hadesmem.googlecode.com/ · C++ Header · 501 lines · 388 code · 68 blank · 45 comment · 4 complexity · c71d1a46cb6b99bbdcbb15c9a92777c0 MD5 · raw file

  1. ///////////////////////////////////////////////////////////////////////////////
  2. /// \file decltype.hpp
  3. /// Contains definition the BOOST_PROTO_DECLTYPE_() macro and assorted helpers
  4. //
  5. // Copyright 2008 Eric Niebler. Distributed under the Boost
  6. // Software License, Version 1.0. (See accompanying file
  7. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  8. #ifndef BOOST_PROTO_DETAIL_DECLTYPE_HPP_EAN_04_04_2008
  9. #define BOOST_PROTO_DETAIL_DECLTYPE_HPP_EAN_04_04_2008
  10. #include <boost/config.hpp>
  11. #include <boost/detail/workaround.hpp>
  12. #include <boost/get_pointer.hpp>
  13. #include <boost/preprocessor/cat.hpp>
  14. #include <boost/preprocessor/repetition/enum_params.hpp>
  15. #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
  16. #include <boost/preprocessor/repetition/enum_binary_params.hpp>
  17. #include <boost/preprocessor/repetition/repeat.hpp>
  18. #include <boost/preprocessor/repetition/repeat_from_to.hpp>
  19. #include <boost/preprocessor/iteration/local.hpp>
  20. #include <boost/mpl/if.hpp>
  21. #include <boost/mpl/eval_if.hpp>
  22. #include <boost/mpl/identity.hpp>
  23. #include <boost/type_traits/is_class.hpp>
  24. #include <boost/type_traits/remove_reference.hpp>
  25. #include <boost/type_traits/is_pointer.hpp>
  26. #include <boost/type_traits/is_function.hpp>
  27. #include <boost/type_traits/is_member_object_pointer.hpp>
  28. #include <boost/type_traits/add_const.hpp>
  29. #include <boost/type_traits/add_reference.hpp>
  30. #include <boost/typeof/typeof.hpp>
  31. #include <boost/utility/addressof.hpp>
  32. #include <boost/utility/result_of.hpp>
  33. #include <boost/utility/enable_if.hpp>
  34. #ifndef BOOST_NO_DECLTYPE
  35. # define BOOST_PROTO_DECLTYPE_(EXPR, TYPE) typedef decltype(EXPR) TYPE;
  36. #else
  37. # define BOOST_PROTO_DECLTYPE_NESTED_TYPEDEF_TPL_(NESTED, EXPR) \
  38. BOOST_TYPEOF_NESTED_TYPEDEF_TPL(BOOST_PP_CAT(nested_and_hidden_, NESTED), EXPR) \
  39. static int const sz = sizeof(boost::proto::detail::check_reference(EXPR)); \
  40. struct NESTED \
  41. : boost::mpl::if_c< \
  42. 1==sz \
  43. , typename BOOST_PP_CAT(nested_and_hidden_, NESTED)::type & \
  44. , typename BOOST_PP_CAT(nested_and_hidden_, NESTED)::type \
  45. > \
  46. {};
  47. # define BOOST_PROTO_DECLTYPE_(EXPR, TYPE) \
  48. BOOST_PROTO_DECLTYPE_NESTED_TYPEDEF_TPL_(BOOST_PP_CAT(nested_, TYPE), (EXPR)) \
  49. typedef typename BOOST_PP_CAT(nested_, TYPE)::type TYPE;
  50. #endif
  51. namespace boost { namespace proto
  52. {
  53. namespace detail
  54. {
  55. namespace anyns
  56. {
  57. ////////////////////////////////////////////////////////////////////////////////////////////
  58. struct any
  59. {
  60. any(...);
  61. any operator=(any);
  62. any operator[](any);
  63. #define M0(Z, N, DATA) any operator()(BOOST_PP_ENUM_PARAMS_Z(Z, N, any BOOST_PP_INTERCEPT));
  64. BOOST_PP_REPEAT(BOOST_PROTO_MAX_ARITY, M0, ~)
  65. #undef M0
  66. template<typename T>
  67. operator T &() const volatile;
  68. any operator+();
  69. any operator-();
  70. any operator*();
  71. any operator&();
  72. any operator~();
  73. any operator!();
  74. any operator++();
  75. any operator--();
  76. any operator++(int);
  77. any operator--(int);
  78. friend any operator<<(any, any);
  79. friend any operator>>(any, any);
  80. friend any operator*(any, any);
  81. friend any operator/(any, any);
  82. friend any operator%(any, any);
  83. friend any operator+(any, any);
  84. friend any operator-(any, any);
  85. friend any operator<(any, any);
  86. friend any operator>(any, any);
  87. friend any operator<=(any, any);
  88. friend any operator>=(any, any);
  89. friend any operator==(any, any);
  90. friend any operator!=(any, any);
  91. friend any operator||(any, any);
  92. friend any operator&&(any, any);
  93. friend any operator&(any, any);
  94. friend any operator|(any, any);
  95. friend any operator^(any, any);
  96. friend any operator,(any, any);
  97. friend any operator->*(any, any);
  98. friend any operator<<=(any, any);
  99. friend any operator>>=(any, any);
  100. friend any operator*=(any, any);
  101. friend any operator/=(any, any);
  102. friend any operator%=(any, any);
  103. friend any operator+=(any, any);
  104. friend any operator-=(any, any);
  105. friend any operator&=(any, any);
  106. friend any operator|=(any, any);
  107. friend any operator^=(any, any);
  108. };
  109. }
  110. using anyns::any;
  111. ////////////////////////////////////////////////////////////////////////////////////////////
  112. template<typename T>
  113. struct as_mutable
  114. {
  115. typedef T &type;
  116. };
  117. template<typename T>
  118. struct as_mutable<T &>
  119. {
  120. typedef T &type;
  121. };
  122. template<typename T>
  123. struct as_mutable<T const &>
  124. {
  125. typedef T &type;
  126. };
  127. ////////////////////////////////////////////////////////////////////////////////////////////
  128. template<typename T>
  129. T make();
  130. ////////////////////////////////////////////////////////////////////////////////////////////
  131. template<typename T>
  132. typename as_mutable<T>::type make_mutable();
  133. ////////////////////////////////////////////////////////////////////////////////////////////
  134. template<typename T>
  135. struct subscript_wrapper
  136. : T
  137. {
  138. using T::operator[];
  139. #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500))
  140. any operator[](any const volatile &) const volatile;
  141. #else
  142. any operator[](any const &) const volatile;
  143. #endif
  144. };
  145. ////////////////////////////////////////////////////////////////////////////////////////////
  146. template<typename T>
  147. struct as_subscriptable
  148. {
  149. typedef
  150. typename mpl::if_c<
  151. is_class<T>::value
  152. , subscript_wrapper<T>
  153. , T
  154. >::type
  155. type;
  156. };
  157. template<typename T>
  158. struct as_subscriptable<T const>
  159. {
  160. typedef
  161. typename mpl::if_c<
  162. is_class<T>::value
  163. , subscript_wrapper<T> const
  164. , T const
  165. >::type
  166. type;
  167. };
  168. template<typename T>
  169. struct as_subscriptable<T &>
  170. {
  171. typedef
  172. typename mpl::if_c<
  173. is_class<T>::value
  174. , subscript_wrapper<T> &
  175. , T &
  176. >::type
  177. type;
  178. };
  179. template<typename T>
  180. struct as_subscriptable<T const &>
  181. {
  182. typedef
  183. typename mpl::if_c<
  184. is_class<T>::value
  185. , subscript_wrapper<T> const &
  186. , T const &
  187. >::type
  188. type;
  189. };
  190. ////////////////////////////////////////////////////////////////////////////////////////////
  191. template<typename T>
  192. typename as_subscriptable<T>::type make_subscriptable();
  193. ////////////////////////////////////////////////////////////////////////////////////////////
  194. template<typename T>
  195. char check_reference(T &);
  196. template<typename T>
  197. char (&check_reference(T const &))[2];
  198. namespace has_get_pointerns
  199. {
  200. using boost::get_pointer;
  201. void *(&get_pointer(...))[2];
  202. ////////////////////////////////////////////////////////////////////////////////////////////
  203. template<typename T>
  204. struct has_get_pointer
  205. {
  206. static const bool value = sizeof(void *) == sizeof(get_pointer(make<T &>()));
  207. typedef mpl::bool_<value> type;
  208. };
  209. }
  210. using has_get_pointerns::has_get_pointer;
  211. ////////////////////////////////////////////////////////////////////////////////////////////
  212. template<typename T>
  213. struct classtypeof;
  214. template<typename T, typename U>
  215. struct classtypeof<T U::*>
  216. {
  217. typedef U type;
  218. };
  219. // Other specializations are generated by the preprocessor
  220. #include <boost/proto/detail/classtypeof.hpp>
  221. ////////////////////////////////////////////////////////////////////////////////////////////
  222. template<typename T>
  223. T &lvalue(T &t)
  224. {
  225. return t;
  226. }
  227. template<typename T>
  228. T const &lvalue(T const &t)
  229. {
  230. return t;
  231. }
  232. ////////////////////////////////////////////////////////////////////////////////////////////
  233. template<typename U, typename V, typename T>
  234. U *proto_get_pointer(T &t, V *, U *)
  235. {
  236. return boost::addressof(t);
  237. }
  238. template<typename U, typename V, typename T>
  239. U const *proto_get_pointer(T &t, V *, U const *)
  240. {
  241. return boost::addressof(t);
  242. }
  243. template<typename U, typename V, typename T>
  244. V *proto_get_pointer(T &t, V *, ...)
  245. {
  246. return get_pointer(t);
  247. }
  248. ////////////////////////////////////////////////////////////////////////////////////////////
  249. #define BOOST_PROTO_USE_GET_POINTER() \
  250. using namespace boost::proto::detail::get_pointerns \
  251. /**/
  252. #define BOOST_PROTO_GET_POINTER(Type, Obj) \
  253. boost::proto::detail::proto_get_pointer<Type>( \
  254. boost::proto::detail::lvalue(Obj) \
  255. , (true ? 0 : get_pointer(Obj)) \
  256. , (true ? 0 : boost::addressof(boost::proto::detail::lvalue(Obj))) \
  257. ) \
  258. /**/
  259. ////////////////////////////////////////////////////////////////////////////////////////////
  260. namespace get_pointerns
  261. {
  262. using boost::get_pointer;
  263. template<typename T>
  264. typename disable_if_c<has_get_pointer<T>::value, T *>::type
  265. get_pointer(T &t)
  266. {
  267. return boost::addressof(t);
  268. }
  269. template<typename T>
  270. typename disable_if_c<has_get_pointer<T>::value, T const *>::type
  271. get_pointer(T const &t)
  272. {
  273. return boost::addressof(t);
  274. }
  275. char test_ptr_to_const(void *);
  276. char (&test_ptr_to_const(void const *))[2];
  277. template<typename U> char test_V_is_a_U(U *);
  278. template<typename U> char test_V_is_a_U(U const *);
  279. template<typename U> char (&test_V_is_a_U(...))[2];
  280. ////////////////////////////////////////////////////////////////////////////////////////////
  281. // result_of_ is a wrapper around boost::result_of that also handles "invocations" of
  282. // member object pointers.
  283. template<typename T, typename Void = void>
  284. struct result_of_
  285. : BOOST_PROTO_RESULT_OF<T>
  286. {};
  287. template<typename T, typename U, typename V>
  288. struct result_of_<T U::*(V), typename enable_if_c<is_member_object_pointer<T U::*>::value>::type>
  289. {
  290. static const bool is_V_a_smart_ptr = 2 == sizeof(test_V_is_a_U<U>(&lvalue(make<V>())));
  291. static const bool is_ptr_to_const = 2 == sizeof(test_ptr_to_const(BOOST_PROTO_GET_POINTER(U, make<V>())));
  292. // If V is not a U, then it is a (smart) pointer and we can always return an lvalue.
  293. // Otherwise, we can only return an lvalue if we are given one.
  294. typedef
  295. typename mpl::eval_if_c<
  296. (is_V_a_smart_ptr || is_reference<V>::value)
  297. , mpl::eval_if_c<
  298. is_ptr_to_const
  299. , add_reference<typename add_const<T>::type>
  300. , add_reference<T>
  301. >
  302. , mpl::identity<T>
  303. >::type
  304. type;
  305. };
  306. ////////////////////////////////////////////////////////////////////////////////////////////
  307. template<
  308. typename T
  309. , typename U
  310. , bool IsMemPtr = is_member_object_pointer<
  311. typename remove_reference<U>::type
  312. >::value
  313. >
  314. struct mem_ptr_fun
  315. {
  316. BOOST_PROTO_DECLTYPE_(
  317. proto::detail::make_mutable<T>() ->* proto::detail::make<U>()
  318. , result_type
  319. )
  320. result_type operator()(
  321. typename add_reference<typename add_const<T>::type>::type t
  322. , typename add_reference<typename add_const<U>::type>::type u
  323. ) const
  324. {
  325. return t ->* u;
  326. }
  327. };
  328. ////////////////////////////////////////////////////////////////////////////////////////////
  329. template<typename T, typename U>
  330. struct mem_ptr_fun<T, U, true>
  331. {
  332. typedef
  333. typename classtypeof<
  334. typename uncvref<U>::type
  335. >::type
  336. V;
  337. BOOST_PROTO_DECLTYPE_(
  338. BOOST_PROTO_GET_POINTER(V, proto::detail::make_mutable<T>()) ->* proto::detail::make<U>()
  339. , result_type
  340. )
  341. result_type operator()(
  342. typename add_reference<typename add_const<T>::type>::type t
  343. , U u
  344. ) const
  345. {
  346. return BOOST_PROTO_GET_POINTER(V, t) ->* u;
  347. }
  348. };
  349. }
  350. using get_pointerns::result_of_;
  351. using get_pointerns::mem_ptr_fun;
  352. ////////////////////////////////////////////////////////////////////////////////////////////
  353. template<typename A0, typename A1>
  354. struct comma_result
  355. {
  356. BOOST_PROTO_DECLTYPE_((proto::detail::make<A0>(), proto::detail::make<A1>()), type)
  357. };
  358. template<typename A0>
  359. struct comma_result<A0, void>
  360. {
  361. typedef void type;
  362. };
  363. template<typename A1>
  364. struct comma_result<void, A1>
  365. {
  366. typedef A1 type;
  367. };
  368. template<>
  369. struct comma_result<void, void>
  370. {
  371. typedef void type;
  372. };
  373. ////////////////////////////////////////////////////////////////////////////////////////////
  374. // normalize a function type for use with boost::result_of
  375. template<typename T, typename U = T>
  376. struct result_of_fixup
  377. : mpl::if_c<is_function<T>::value, T *, U>
  378. {};
  379. template<typename T, typename U>
  380. struct result_of_fixup<T &, U>
  381. : result_of_fixup<T, T>
  382. {};
  383. template<typename T, typename U>
  384. struct result_of_fixup<T const &, U>
  385. : result_of_fixup<T, T>
  386. {};
  387. template<typename T, typename U>
  388. struct result_of_fixup<T *, U>
  389. : result_of_fixup<T, U>
  390. {};
  391. template<typename R, typename T, typename U>
  392. struct result_of_fixup<R T::*, U>
  393. {
  394. typedef R T::*type;
  395. };
  396. template<typename T, typename U>
  397. struct result_of_fixup<T const, U>
  398. : result_of_fixup<T, U>
  399. {};
  400. //// Tests for result_of_fixup
  401. //struct bar {};
  402. //BOOST_MPL_ASSERT((is_same<bar, result_of_fixup<bar>::type>));
  403. //BOOST_MPL_ASSERT((is_same<bar const, result_of_fixup<bar const>::type>));
  404. //BOOST_MPL_ASSERT((is_same<bar, result_of_fixup<bar &>::type>));
  405. //BOOST_MPL_ASSERT((is_same<bar const, result_of_fixup<bar const &>::type>));
  406. //BOOST_MPL_ASSERT((is_same<void(*)(), result_of_fixup<void(*)()>::type>));
  407. //BOOST_MPL_ASSERT((is_same<void(*)(), result_of_fixup<void(* const)()>::type>));
  408. //BOOST_MPL_ASSERT((is_same<void(*)(), result_of_fixup<void(* const &)()>::type>));
  409. //BOOST_MPL_ASSERT((is_same<void(*)(), result_of_fixup<void(&)()>::type>));
  410. template<typename T, typename PMF>
  411. struct memfun
  412. {
  413. typedef typename uncvref<PMF>::type pmf_type;
  414. typedef typename classtypeof<pmf_type>::type V;
  415. typedef typename BOOST_PROTO_RESULT_OF<pmf_type(T)>::type result_type;
  416. memfun(T t, PMF p)
  417. : obj(t)
  418. , pmf(p)
  419. {}
  420. result_type operator()() const
  421. {
  422. BOOST_PROTO_USE_GET_POINTER();
  423. return (BOOST_PROTO_GET_POINTER(V, obj) ->* pmf)();
  424. }
  425. // Other overloads generated by the preprocessor
  426. #include <boost/proto/detail/memfun_funop.hpp>
  427. private:
  428. T obj;
  429. PMF pmf;
  430. };
  431. } // namespace detail
  432. }}
  433. #endif