meta_utils.hpp 15 KB

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