meta_utils.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2012-2015.
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // (See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. // See http://www.boost.org/libs/move for documentation.
  9. //
  10. //////////////////////////////////////////////////////////////////////////////
  11. //! \file
  12. #ifndef BOOST_MOVE_DETAIL_META_UTILS_HPP
  13. #define BOOST_MOVE_DETAIL_META_UTILS_HPP
  14. #if defined(BOOST_HAS_PRAGMA_ONCE)
  15. # pragma once
  16. #endif
  17. #include <boost/move/detail/workaround.hpp> //forceinline
  18. #include <boost/move/detail/meta_utils_core.hpp>
  19. #include <boost/move/detail/addressof.hpp>
  20. //Small meta-typetraits to support move
  21. namespace boost {
  22. //Forward declare boost::rv
  23. template <class T> class rv;
  24. namespace move_detail {
  25. //////////////////////////////////////
  26. // is_different
  27. //////////////////////////////////////
  28. template<class T, class U>
  29. struct is_different
  30. {
  31. static const bool value = !is_same<T, U>::value;
  32. };
  33. //////////////////////////////////////
  34. // apply
  35. //////////////////////////////////////
  36. template<class F, class Param>
  37. struct apply
  38. {
  39. typedef typename F::template apply<Param>::type type;
  40. };
  41. //////////////////////////////////////
  42. // bool_
  43. //////////////////////////////////////
  44. template< bool C_ >
  45. struct bool_ : integral_constant<bool, C_>
  46. {
  47. inline operator bool() const { return C_; }
  48. inline bool operator()() const { return C_; }
  49. };
  50. typedef bool_<true> true_;
  51. typedef bool_<false> false_;
  52. //////////////////////////////////////
  53. // nat
  54. //////////////////////////////////////
  55. struct nat{};
  56. struct nat2{};
  57. struct nat3{};
  58. template <unsigned N>
  59. struct natN
  60. {};
  61. //////////////////////////////////////
  62. // yes_type/no_type
  63. //////////////////////////////////////
  64. typedef char yes_type;
  65. struct no_type
  66. {
  67. char _[2];
  68. };
  69. //////////////////////////////////////
  70. // natify
  71. //////////////////////////////////////
  72. template <class T> struct natify{};
  73. //////////////////////////////////////
  74. // remove_reference
  75. //////////////////////////////////////
  76. template<class T>
  77. struct remove_reference
  78. {
  79. typedef T type;
  80. };
  81. template<class T>
  82. struct remove_reference<T&>
  83. {
  84. typedef T type;
  85. };
  86. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  87. template<class T>
  88. struct remove_reference<T&&>
  89. {
  90. typedef T type;
  91. };
  92. #else
  93. template<class T>
  94. struct remove_reference< rv<T> >
  95. {
  96. typedef T type;
  97. };
  98. template<class T>
  99. struct remove_reference< rv<T> &>
  100. {
  101. typedef T type;
  102. };
  103. template<class T>
  104. struct remove_reference< const rv<T> &>
  105. {
  106. typedef T type;
  107. };
  108. #endif
  109. //////////////////////////////////////
  110. // remove_pointer
  111. //////////////////////////////////////
  112. template< class T > struct remove_pointer { typedef T type; };
  113. template< class T > struct remove_pointer<T*> { typedef T type; };
  114. template< class T > struct remove_pointer<T* const> { typedef T type; };
  115. template< class T > struct remove_pointer<T* volatile> { typedef T type; };
  116. template< class T > struct remove_pointer<T* const volatile> { typedef T type; };
  117. //////////////////////////////////////
  118. // add_pointer
  119. //////////////////////////////////////
  120. template< class T >
  121. struct add_pointer
  122. {
  123. typedef typename remove_reference<T>::type* type;
  124. };
  125. //////////////////////////////////////
  126. // add_const
  127. //////////////////////////////////////
  128. template<class T>
  129. struct add_const
  130. {
  131. typedef const T type;
  132. };
  133. template<class T>
  134. struct add_const<T&>
  135. {
  136. typedef const T& type;
  137. };
  138. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  139. template<class T>
  140. struct add_const<T&&>
  141. {
  142. typedef T&& type;
  143. };
  144. #endif
  145. //////////////////////////////////////
  146. // add_lvalue_reference
  147. //////////////////////////////////////
  148. template<class T>
  149. struct add_lvalue_reference
  150. { typedef T& type; };
  151. template<class T> struct add_lvalue_reference<T&> { typedef T& type; };
  152. template<> struct add_lvalue_reference<void> { typedef void type; };
  153. template<> struct add_lvalue_reference<const void> { typedef const void type; };
  154. template<> struct add_lvalue_reference<volatile void> { typedef volatile void type; };
  155. template<> struct add_lvalue_reference<const volatile void>{ typedef const volatile void type; };
  156. template<class T>
  157. struct add_const_lvalue_reference
  158. {
  159. typedef typename remove_reference<T>::type t_unreferenced;
  160. typedef typename add_const<t_unreferenced>::type t_unreferenced_const;
  161. typedef typename add_lvalue_reference
  162. <t_unreferenced_const>::type type;
  163. };
  164. //////////////////////////////////////
  165. // identity
  166. //////////////////////////////////////
  167. template <class T>
  168. struct identity
  169. {
  170. typedef T type;
  171. typedef typename add_const_lvalue_reference<T>::type reference;
  172. BOOST_MOVE_FORCEINLINE reference operator()(reference t) const
  173. { return t; }
  174. };
  175. //////////////////////////////////////
  176. // is_class_or_union
  177. //////////////////////////////////////
  178. template<class T>
  179. struct is_class_or_union
  180. {
  181. struct twochar { char dummy[2]; };
  182. template <class U>
  183. static char is_class_or_union_tester(void(U::*)(void));
  184. template <class U>
  185. static twochar is_class_or_union_tester(...);
  186. static const bool value = sizeof(is_class_or_union_tester<T>(0)) == sizeof(char);
  187. };
  188. //////////////////////////////////////
  189. // addressof
  190. //////////////////////////////////////
  191. //////////////////////////////////////
  192. // has_pointer_type
  193. //////////////////////////////////////
  194. template <class T>
  195. struct has_pointer_type
  196. {
  197. struct two { char c[2]; };
  198. template <class U> static two test(...);
  199. template <class U> static char test(typename U::pointer* = 0);
  200. static const bool value = sizeof(test<T>(0)) == 1;
  201. };
  202. //////////////////////////////////////
  203. // is_convertible
  204. //////////////////////////////////////
  205. #if defined(_MSC_VER) && (_MSC_VER >= 1400)
  206. //use intrinsic since in MSVC
  207. //overaligned types can't go through ellipsis
  208. template <class T, class U>
  209. struct is_convertible
  210. {
  211. static const bool value = __is_convertible_to(T, U);
  212. };
  213. #else
  214. template <class T, class U>
  215. class is_convertible
  216. {
  217. typedef typename add_lvalue_reference<T>::type t_reference;
  218. typedef char true_t;
  219. class false_t { char dummy[2]; };
  220. static false_t dispatch(...);
  221. static true_t dispatch(U);
  222. static t_reference trigger();
  223. public:
  224. static const bool value = sizeof(dispatch(trigger())) == sizeof(true_t);
  225. };
  226. #endif
  227. template <class T, class U, bool IsSame = is_same<T, U>::value>
  228. struct is_same_or_convertible
  229. : is_convertible<T, U>
  230. {};
  231. template <class T, class U>
  232. struct is_same_or_convertible<T, U, true>
  233. {
  234. static const bool value = true;
  235. };
  236. template<
  237. bool C
  238. , typename F1
  239. , typename F2
  240. >
  241. struct eval_if_c
  242. : if_c<C,F1,F2>::type
  243. {};
  244. template<
  245. typename C
  246. , typename T1
  247. , typename T2
  248. >
  249. struct eval_if
  250. : if_<C,T1,T2>::type
  251. {};
  252. #if defined(BOOST_GCC) && (BOOST_GCC <= 40000)
  253. #define BOOST_MOVE_HELPERS_RETURN_SFINAE_BROKEN
  254. #endif
  255. template<class T, class U, class R = void>
  256. struct enable_if_convertible
  257. : enable_if< is_convertible<T, U>, R>
  258. {};
  259. template<class T, class U, class R = void>
  260. struct disable_if_convertible
  261. : disable_if< is_convertible<T, U>, R>
  262. {};
  263. template<class T, class U, class R = void>
  264. struct enable_if_same_or_convertible
  265. : enable_if< is_same_or_convertible<T, U>, R>
  266. {};
  267. template<class T, class U, class R = void>
  268. struct disable_if_same_or_convertible
  269. : disable_if< is_same_or_convertible<T, U>, R>
  270. {};
  271. //////////////////////////////////////////////////////////////////////////////
  272. //
  273. // and_
  274. //
  275. //////////////////////////////////////////////////////////////////////////////
  276. template<bool, class B = true_, class C = true_, class D = true_>
  277. struct and_impl
  278. : and_impl<B::value, C, D>
  279. {};
  280. template<>
  281. struct and_impl<true, true_, true_, true_>
  282. {
  283. static const bool value = true;
  284. };
  285. template<class B, class C, class D>
  286. struct and_impl<false, B, C, D>
  287. {
  288. static const bool value = false;
  289. };
  290. template<class A, class B, class C = true_, class D = true_>
  291. struct and_
  292. : and_impl<A::value, B, C, D>
  293. {};
  294. //////////////////////////////////////////////////////////////////////////////
  295. //
  296. // or_
  297. //
  298. //////////////////////////////////////////////////////////////////////////////
  299. template<bool, class B = false_, class C = false_, class D = false_>
  300. struct or_impl
  301. : or_impl<B::value, C, D>
  302. {};
  303. template<>
  304. struct or_impl<false, false_, false_, false_>
  305. {
  306. static const bool value = false;
  307. };
  308. template<class B, class C, class D>
  309. struct or_impl<true, B, C, D>
  310. {
  311. static const bool value = true;
  312. };
  313. template<class A, class B, class C = false_, class D = false_>
  314. struct or_
  315. : or_impl<A::value, B, C, D>
  316. {};
  317. //////////////////////////////////////////////////////////////////////////////
  318. //
  319. // not_
  320. //
  321. //////////////////////////////////////////////////////////////////////////////
  322. template<class T>
  323. struct not_
  324. {
  325. static const bool value = !T::value;
  326. };
  327. //////////////////////////////////////////////////////////////////////////////
  328. //
  329. // enable_if_and / disable_if_and / enable_if_or / disable_if_or
  330. //
  331. //////////////////////////////////////////////////////////////////////////////
  332. template<class R, class A, class B, class C = true_, class D = true_>
  333. struct enable_if_and
  334. : enable_if_c< and_<A, B, C, D>::value, R>
  335. {};
  336. template<class R, class A, class B, class C = true_, class D = true_>
  337. struct disable_if_and
  338. : disable_if_c< and_<A, B, C, D>::value, R>
  339. {};
  340. template<class R, class A, class B, class C = false_, class D = false_>
  341. struct enable_if_or
  342. : enable_if_c< or_<A, B, C, D>::value, R>
  343. {};
  344. template<class R, class A, class B, class C = false_, class D = false_>
  345. struct disable_if_or
  346. : disable_if_c< or_<A, B, C, D>::value, R>
  347. {};
  348. //////////////////////////////////////////////////////////////////////////////
  349. //
  350. // has_move_emulation_enabled_impl
  351. //
  352. //////////////////////////////////////////////////////////////////////////////
  353. template<class T>
  354. struct has_move_emulation_enabled_impl
  355. : is_convertible< T, ::boost::rv<T>& >
  356. {};
  357. template<class T>
  358. struct has_move_emulation_enabled_impl<T&>
  359. { static const bool value = false; };
  360. template<class T>
  361. struct has_move_emulation_enabled_impl< ::boost::rv<T> >
  362. { static const bool value = false; };
  363. //////////////////////////////////////////////////////////////////////////////
  364. //
  365. // is_rv_impl
  366. //
  367. //////////////////////////////////////////////////////////////////////////////
  368. template <class T>
  369. struct is_rv_impl
  370. { static const bool value = false; };
  371. template <class T>
  372. struct is_rv_impl< rv<T> >
  373. { static const bool value = true; };
  374. template <class T>
  375. struct is_rv_impl< const rv<T> >
  376. { static const bool value = true; };
  377. // Code from Jeffrey Lee Hellrung, many thanks
  378. template< class T >
  379. struct is_rvalue_reference
  380. { static const bool value = false; };
  381. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  382. template< class T >
  383. struct is_rvalue_reference< T&& >
  384. { static const bool value = true; };
  385. #else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  386. template< class T >
  387. struct is_rvalue_reference< boost::rv<T>& >
  388. { static const bool value = true; };
  389. template< class T >
  390. struct is_rvalue_reference< const boost::rv<T>& >
  391. { static const bool value = true; };
  392. #endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  393. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  394. template< class T >
  395. struct add_rvalue_reference
  396. { typedef T&& type; };
  397. #else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  398. namespace detail_add_rvalue_reference
  399. {
  400. template< class T
  401. , bool emulation = has_move_emulation_enabled_impl<T>::value
  402. , bool rv = is_rv_impl<T>::value >
  403. struct add_rvalue_reference_impl { typedef T type; };
  404. template< class T, bool emulation>
  405. struct add_rvalue_reference_impl< T, emulation, true > { typedef T & type; };
  406. template< class T, bool rv >
  407. struct add_rvalue_reference_impl< T, true, rv > { typedef ::boost::rv<T>& type; };
  408. } // namespace detail_add_rvalue_reference
  409. template< class T >
  410. struct add_rvalue_reference
  411. : detail_add_rvalue_reference::add_rvalue_reference_impl<T>
  412. { };
  413. template< class T >
  414. struct add_rvalue_reference<T &>
  415. { typedef T & type; };
  416. #endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  417. template< class T > struct remove_rvalue_reference { typedef T type; };
  418. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  419. template< class T > struct remove_rvalue_reference< T&& > { typedef T type; };
  420. #else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  421. template< class T > struct remove_rvalue_reference< rv<T> > { typedef T type; };
  422. template< class T > struct remove_rvalue_reference< const rv<T> > { typedef T type; };
  423. template< class T > struct remove_rvalue_reference< volatile rv<T> > { typedef T type; };
  424. template< class T > struct remove_rvalue_reference< const volatile rv<T> > { typedef T type; };
  425. template< class T > struct remove_rvalue_reference< rv<T>& > { typedef T type; };
  426. template< class T > struct remove_rvalue_reference< const rv<T>& > { typedef T type; };
  427. template< class T > struct remove_rvalue_reference< volatile rv<T>& > { typedef T type; };
  428. template< class T > struct remove_rvalue_reference< const volatile rv<T>& >{ typedef T type; };
  429. #endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  430. // Ideas from Boost.Move review, Jeffrey Lee Hellrung:
  431. //
  432. //- TypeTraits metafunctions is_lvalue_reference, add_lvalue_reference, and remove_lvalue_reference ?
  433. // Perhaps add_reference and remove_reference can be modified so that they behave wrt emulated rvalue
  434. // references the same as wrt real rvalue references, i.e., add_reference< rv<T>& > -> T& rather than
  435. // rv<T>& (since T&& & -> T&).
  436. //
  437. //- Add'l TypeTraits has_[trivial_]move_{constructor,assign}...?
  438. //
  439. //- An as_lvalue(T& x) function, which amounts to an identity operation in C++0x, but strips emulated
  440. // rvalue references in C++03. This may be necessary to prevent "accidental moves".
  441. } //namespace move_detail {
  442. } //namespace boost {
  443. #endif //#ifndef BOOST_MOVE_DETAIL_META_UTILS_HPP