meta_utils.hpp 15 KB

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