meta_utils.hpp 15 KB

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