alloc_traits.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  1. // Allocator traits -*- C++ -*-
  2. // Copyright (C) 2011-2018 Free Software Foundation, Inc.
  3. //
  4. // This file is part of the GNU ISO C++ Library. This library is free
  5. // software; you can redistribute it and/or modify it under the
  6. // terms of the GNU General Public License as published by the
  7. // Free Software Foundation; either version 3, or (at your option)
  8. // any later version.
  9. // This library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // Under Section 7 of GPL version 3, you are granted additional
  14. // permissions described in the GCC Runtime Library Exception, version
  15. // 3.1, as published by the Free Software Foundation.
  16. // You should have received a copy of the GNU General Public License and
  17. // a copy of the GCC Runtime Library Exception along with this program;
  18. // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. // <http://www.gnu.org/licenses/>.
  20. /** @file bits/alloc_traits.h
  21. * This is an internal header file, included by other library headers.
  22. * Do not attempt to use it directly. @headername{memory}
  23. */
  24. #ifndef _ALLOC_TRAITS_H
  25. #define _ALLOC_TRAITS_H 1
  26. #if __cplusplus >= 201103L
  27. #include <bits/memoryfwd.h>
  28. #include <bits/ptr_traits.h>
  29. #include <ext/numeric_traits.h>
  30. #define __cpp_lib_allocator_traits_is_always_equal 201411
  31. namespace std _GLIBCXX_VISIBILITY(default)
  32. {
  33. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  34. struct __allocator_traits_base
  35. {
  36. template<typename _Tp, typename _Up, typename = void>
  37. struct __rebind : __replace_first_arg<_Tp, _Up> { };
  38. template<typename _Tp, typename _Up>
  39. struct __rebind<_Tp, _Up,
  40. __void_t<typename _Tp::template rebind<_Up>::other>>
  41. { using type = typename _Tp::template rebind<_Up>::other; };
  42. protected:
  43. template<typename _Tp>
  44. using __pointer = typename _Tp::pointer;
  45. template<typename _Tp>
  46. using __c_pointer = typename _Tp::const_pointer;
  47. template<typename _Tp>
  48. using __v_pointer = typename _Tp::void_pointer;
  49. template<typename _Tp>
  50. using __cv_pointer = typename _Tp::const_void_pointer;
  51. template<typename _Tp>
  52. using __pocca = typename _Tp::propagate_on_container_copy_assignment;
  53. template<typename _Tp>
  54. using __pocma = typename _Tp::propagate_on_container_move_assignment;
  55. template<typename _Tp>
  56. using __pocs = typename _Tp::propagate_on_container_swap;
  57. template<typename _Tp>
  58. using __equal = typename _Tp::is_always_equal;
  59. };
  60. template<typename _Alloc, typename _Up>
  61. using __alloc_rebind
  62. = typename __allocator_traits_base::template __rebind<_Alloc, _Up>::type;
  63. /**
  64. * @brief Uniform interface to all allocator types.
  65. * @ingroup allocators
  66. */
  67. template<typename _Alloc>
  68. struct allocator_traits : __allocator_traits_base
  69. {
  70. /// The allocator type
  71. typedef _Alloc allocator_type;
  72. /// The allocated type
  73. typedef typename _Alloc::value_type value_type;
  74. /**
  75. * @brief The allocator's pointer type.
  76. *
  77. * @c Alloc::pointer if that type exists, otherwise @c value_type*
  78. */
  79. using pointer = __detected_or_t<value_type*, __pointer, _Alloc>;
  80. private:
  81. // Select _Func<_Alloc> or pointer_traits<pointer>::rebind<_Tp>
  82. template<template<typename> class _Func, typename _Tp, typename = void>
  83. struct _Ptr
  84. {
  85. using type = typename pointer_traits<pointer>::template rebind<_Tp>;
  86. };
  87. template<template<typename> class _Func, typename _Tp>
  88. struct _Ptr<_Func, _Tp, __void_t<_Func<_Alloc>>>
  89. {
  90. using type = _Func<_Alloc>;
  91. };
  92. // Select _A2::difference_type or pointer_traits<_Ptr>::difference_type
  93. template<typename _A2, typename _PtrT, typename = void>
  94. struct _Diff
  95. { using type = typename pointer_traits<_PtrT>::difference_type; };
  96. template<typename _A2, typename _PtrT>
  97. struct _Diff<_A2, _PtrT, __void_t<typename _A2::difference_type>>
  98. { using type = typename _A2::difference_type; };
  99. // Select _A2::size_type or make_unsigned<_DiffT>::type
  100. template<typename _A2, typename _DiffT, typename = void>
  101. struct _Size : make_unsigned<_DiffT> { };
  102. template<typename _A2, typename _DiffT>
  103. struct _Size<_A2, _DiffT, __void_t<typename _A2::size_type>>
  104. { using type = typename _A2::size_type; };
  105. public:
  106. /**
  107. * @brief The allocator's const pointer type.
  108. *
  109. * @c Alloc::const_pointer if that type exists, otherwise
  110. * <tt> pointer_traits<pointer>::rebind<const value_type> </tt>
  111. */
  112. using const_pointer = typename _Ptr<__c_pointer, const value_type>::type;
  113. /**
  114. * @brief The allocator's void pointer type.
  115. *
  116. * @c Alloc::void_pointer if that type exists, otherwise
  117. * <tt> pointer_traits<pointer>::rebind<void> </tt>
  118. */
  119. using void_pointer = typename _Ptr<__v_pointer, void>::type;
  120. /**
  121. * @brief The allocator's const void pointer type.
  122. *
  123. * @c Alloc::const_void_pointer if that type exists, otherwise
  124. * <tt> pointer_traits<pointer>::rebind<const void> </tt>
  125. */
  126. using const_void_pointer = typename _Ptr<__cv_pointer, const void>::type;
  127. /**
  128. * @brief The allocator's difference type
  129. *
  130. * @c Alloc::difference_type if that type exists, otherwise
  131. * <tt> pointer_traits<pointer>::difference_type </tt>
  132. */
  133. using difference_type = typename _Diff<_Alloc, pointer>::type;
  134. /**
  135. * @brief The allocator's size type
  136. *
  137. * @c Alloc::size_type if that type exists, otherwise
  138. * <tt> make_unsigned<difference_type>::type </tt>
  139. */
  140. using size_type = typename _Size<_Alloc, difference_type>::type;
  141. /**
  142. * @brief How the allocator is propagated on copy assignment
  143. *
  144. * @c Alloc::propagate_on_container_copy_assignment if that type exists,
  145. * otherwise @c false_type
  146. */
  147. using propagate_on_container_copy_assignment
  148. = __detected_or_t<false_type, __pocca, _Alloc>;
  149. /**
  150. * @brief How the allocator is propagated on move assignment
  151. *
  152. * @c Alloc::propagate_on_container_move_assignment if that type exists,
  153. * otherwise @c false_type
  154. */
  155. using propagate_on_container_move_assignment
  156. = __detected_or_t<false_type, __pocma, _Alloc>;
  157. /**
  158. * @brief How the allocator is propagated on swap
  159. *
  160. * @c Alloc::propagate_on_container_swap if that type exists,
  161. * otherwise @c false_type
  162. */
  163. using propagate_on_container_swap
  164. = __detected_or_t<false_type, __pocs, _Alloc>;
  165. /**
  166. * @brief Whether all instances of the allocator type compare equal.
  167. *
  168. * @c Alloc::is_always_equal if that type exists,
  169. * otherwise @c is_empty<Alloc>::type
  170. */
  171. using is_always_equal
  172. = __detected_or_t<typename is_empty<_Alloc>::type, __equal, _Alloc>;
  173. template<typename _Tp>
  174. using rebind_alloc = __alloc_rebind<_Alloc, _Tp>;
  175. template<typename _Tp>
  176. using rebind_traits = allocator_traits<rebind_alloc<_Tp>>;
  177. private:
  178. template<typename _Alloc2>
  179. static auto
  180. _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer __hint, int)
  181. -> decltype(__a.allocate(__n, __hint))
  182. { return __a.allocate(__n, __hint); }
  183. template<typename _Alloc2>
  184. static pointer
  185. _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer, ...)
  186. { return __a.allocate(__n); }
  187. template<typename _Tp, typename... _Args>
  188. struct __construct_helper
  189. {
  190. template<typename _Alloc2,
  191. typename = decltype(std::declval<_Alloc2*>()->construct(
  192. std::declval<_Tp*>(), std::declval<_Args>()...))>
  193. static true_type __test(int);
  194. template<typename>
  195. static false_type __test(...);
  196. using type = decltype(__test<_Alloc>(0));
  197. };
  198. template<typename _Tp, typename... _Args>
  199. using __has_construct
  200. = typename __construct_helper<_Tp, _Args...>::type;
  201. template<typename _Tp, typename... _Args>
  202. static _Require<__has_construct<_Tp, _Args...>>
  203. _S_construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
  204. { __a.construct(__p, std::forward<_Args>(__args)...); }
  205. template<typename _Tp, typename... _Args>
  206. static
  207. _Require<__and_<__not_<__has_construct<_Tp, _Args...>>,
  208. is_constructible<_Tp, _Args...>>>
  209. _S_construct(_Alloc&, _Tp* __p, _Args&&... __args)
  210. { ::new((void*)__p) _Tp(std::forward<_Args>(__args)...); }
  211. template<typename _Alloc2, typename _Tp>
  212. static auto
  213. _S_destroy(_Alloc2& __a, _Tp* __p, int)
  214. -> decltype(__a.destroy(__p))
  215. { __a.destroy(__p); }
  216. template<typename _Alloc2, typename _Tp>
  217. static void
  218. _S_destroy(_Alloc2&, _Tp* __p, ...)
  219. { __p->~_Tp(); }
  220. template<typename _Alloc2>
  221. static auto
  222. _S_max_size(_Alloc2& __a, int)
  223. -> decltype(__a.max_size())
  224. { return __a.max_size(); }
  225. template<typename _Alloc2>
  226. static size_type
  227. _S_max_size(_Alloc2&, ...)
  228. {
  229. // _GLIBCXX_RESOLVE_LIB_DEFECTS
  230. // 2466. allocator_traits::max_size() default behavior is incorrect
  231. return __gnu_cxx::__numeric_traits<size_type>::__max
  232. / sizeof(value_type);
  233. }
  234. template<typename _Alloc2>
  235. static auto
  236. _S_select(_Alloc2& __a, int)
  237. -> decltype(__a.select_on_container_copy_construction())
  238. { return __a.select_on_container_copy_construction(); }
  239. template<typename _Alloc2>
  240. static _Alloc2
  241. _S_select(_Alloc2& __a, ...)
  242. { return __a; }
  243. public:
  244. /**
  245. * @brief Allocate memory.
  246. * @param __a An allocator.
  247. * @param __n The number of objects to allocate space for.
  248. *
  249. * Calls @c a.allocate(n)
  250. */
  251. static pointer
  252. allocate(_Alloc& __a, size_type __n)
  253. { return __a.allocate(__n); }
  254. /**
  255. * @brief Allocate memory.
  256. * @param __a An allocator.
  257. * @param __n The number of objects to allocate space for.
  258. * @param __hint Aid to locality.
  259. * @return Memory of suitable size and alignment for @a n objects
  260. * of type @c value_type
  261. *
  262. * Returns <tt> a.allocate(n, hint) </tt> if that expression is
  263. * well-formed, otherwise returns @c a.allocate(n)
  264. */
  265. static pointer
  266. allocate(_Alloc& __a, size_type __n, const_void_pointer __hint)
  267. { return _S_allocate(__a, __n, __hint, 0); }
  268. /**
  269. * @brief Deallocate memory.
  270. * @param __a An allocator.
  271. * @param __p Pointer to the memory to deallocate.
  272. * @param __n The number of objects space was allocated for.
  273. *
  274. * Calls <tt> a.deallocate(p, n) </tt>
  275. */
  276. static void
  277. deallocate(_Alloc& __a, pointer __p, size_type __n)
  278. { __a.deallocate(__p, __n); }
  279. /**
  280. * @brief Construct an object of type @a _Tp
  281. * @param __a An allocator.
  282. * @param __p Pointer to memory of suitable size and alignment for Tp
  283. * @param __args Constructor arguments.
  284. *
  285. * Calls <tt> __a.construct(__p, std::forward<Args>(__args)...) </tt>
  286. * if that expression is well-formed, otherwise uses placement-new
  287. * to construct an object of type @a _Tp at location @a __p from the
  288. * arguments @a __args...
  289. */
  290. template<typename _Tp, typename... _Args>
  291. static auto construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
  292. -> decltype(_S_construct(__a, __p, std::forward<_Args>(__args)...))
  293. { _S_construct(__a, __p, std::forward<_Args>(__args)...); }
  294. /**
  295. * @brief Destroy an object of type @a _Tp
  296. * @param __a An allocator.
  297. * @param __p Pointer to the object to destroy
  298. *
  299. * Calls @c __a.destroy(__p) if that expression is well-formed,
  300. * otherwise calls @c __p->~_Tp()
  301. */
  302. template<typename _Tp>
  303. static void destroy(_Alloc& __a, _Tp* __p)
  304. { _S_destroy(__a, __p, 0); }
  305. /**
  306. * @brief The maximum supported allocation size
  307. * @param __a An allocator.
  308. * @return @c __a.max_size() or @c numeric_limits<size_type>::max()
  309. *
  310. * Returns @c __a.max_size() if that expression is well-formed,
  311. * otherwise returns @c numeric_limits<size_type>::max()
  312. */
  313. static size_type max_size(const _Alloc& __a) noexcept
  314. { return _S_max_size(__a, 0); }
  315. /**
  316. * @brief Obtain an allocator to use when copying a container.
  317. * @param __rhs An allocator.
  318. * @return @c __rhs.select_on_container_copy_construction() or @a __rhs
  319. *
  320. * Returns @c __rhs.select_on_container_copy_construction() if that
  321. * expression is well-formed, otherwise returns @a __rhs
  322. */
  323. static _Alloc
  324. select_on_container_copy_construction(const _Alloc& __rhs)
  325. { return _S_select(__rhs, 0); }
  326. };
  327. /// Partial specialization for std::allocator.
  328. template<typename _Tp>
  329. struct allocator_traits<allocator<_Tp>>
  330. {
  331. /// The allocator type
  332. using allocator_type = allocator<_Tp>;
  333. /// The allocated type
  334. using value_type = _Tp;
  335. /// The allocator's pointer type.
  336. using pointer = _Tp*;
  337. /// The allocator's const pointer type.
  338. using const_pointer = const _Tp*;
  339. /// The allocator's void pointer type.
  340. using void_pointer = void*;
  341. /// The allocator's const void pointer type.
  342. using const_void_pointer = const void*;
  343. /// The allocator's difference type
  344. using difference_type = std::ptrdiff_t;
  345. /// The allocator's size type
  346. using size_type = std::size_t;
  347. /// How the allocator is propagated on copy assignment
  348. using propagate_on_container_copy_assignment = false_type;
  349. /// How the allocator is propagated on move assignment
  350. using propagate_on_container_move_assignment = true_type;
  351. /// How the allocator is propagated on swap
  352. using propagate_on_container_swap = false_type;
  353. /// Whether all instances of the allocator type compare equal.
  354. using is_always_equal = true_type;
  355. template<typename _Up>
  356. using rebind_alloc = allocator<_Up>;
  357. template<typename _Up>
  358. using rebind_traits = allocator_traits<allocator<_Up>>;
  359. /**
  360. * @brief Allocate memory.
  361. * @param __a An allocator.
  362. * @param __n The number of objects to allocate space for.
  363. *
  364. * Calls @c a.allocate(n)
  365. */
  366. static pointer
  367. allocate(allocator_type& __a, size_type __n)
  368. { return __a.allocate(__n); }
  369. /**
  370. * @brief Allocate memory.
  371. * @param __a An allocator.
  372. * @param __n The number of objects to allocate space for.
  373. * @param __hint Aid to locality.
  374. * @return Memory of suitable size and alignment for @a n objects
  375. * of type @c value_type
  376. *
  377. * Returns <tt> a.allocate(n, hint) </tt>
  378. */
  379. static pointer
  380. allocate(allocator_type& __a, size_type __n, const_void_pointer __hint)
  381. { return __a.allocate(__n, __hint); }
  382. /**
  383. * @brief Deallocate memory.
  384. * @param __a An allocator.
  385. * @param __p Pointer to the memory to deallocate.
  386. * @param __n The number of objects space was allocated for.
  387. *
  388. * Calls <tt> a.deallocate(p, n) </tt>
  389. */
  390. static void
  391. deallocate(allocator_type& __a, pointer __p, size_type __n)
  392. { __a.deallocate(__p, __n); }
  393. /**
  394. * @brief Construct an object of type @a _Up
  395. * @param __a An allocator.
  396. * @param __p Pointer to memory of suitable size and alignment for Tp
  397. * @param __args Constructor arguments.
  398. *
  399. * Calls <tt> __a.construct(__p, std::forward<Args>(__args)...) </tt>
  400. */
  401. template<typename _Up, typename... _Args>
  402. static void
  403. construct(allocator_type& __a, _Up* __p, _Args&&... __args)
  404. { __a.construct(__p, std::forward<_Args>(__args)...); }
  405. /**
  406. * @brief Destroy an object of type @a _Up
  407. * @param __a An allocator.
  408. * @param __p Pointer to the object to destroy
  409. *
  410. * Calls @c __a.destroy(__p).
  411. */
  412. template<typename _Up>
  413. static void
  414. destroy(allocator_type& __a, _Up* __p)
  415. { __a.destroy(__p); }
  416. /**
  417. * @brief The maximum supported allocation size
  418. * @param __a An allocator.
  419. * @return @c __a.max_size()
  420. */
  421. static size_type
  422. max_size(const allocator_type& __a) noexcept
  423. { return __a.max_size(); }
  424. /**
  425. * @brief Obtain an allocator to use when copying a container.
  426. * @param __rhs An allocator.
  427. * @return @c __rhs
  428. */
  429. static allocator_type
  430. select_on_container_copy_construction(const allocator_type& __rhs)
  431. { return __rhs; }
  432. };
  433. template<typename _Alloc>
  434. inline void
  435. __do_alloc_on_copy(_Alloc& __one, const _Alloc& __two, true_type)
  436. { __one = __two; }
  437. template<typename _Alloc>
  438. inline void
  439. __do_alloc_on_copy(_Alloc&, const _Alloc&, false_type)
  440. { }
  441. template<typename _Alloc>
  442. inline void __alloc_on_copy(_Alloc& __one, const _Alloc& __two)
  443. {
  444. typedef allocator_traits<_Alloc> __traits;
  445. typedef typename __traits::propagate_on_container_copy_assignment __pocca;
  446. __do_alloc_on_copy(__one, __two, __pocca());
  447. }
  448. template<typename _Alloc>
  449. inline _Alloc __alloc_on_copy(const _Alloc& __a)
  450. {
  451. typedef allocator_traits<_Alloc> __traits;
  452. return __traits::select_on_container_copy_construction(__a);
  453. }
  454. template<typename _Alloc>
  455. inline void __do_alloc_on_move(_Alloc& __one, _Alloc& __two, true_type)
  456. { __one = std::move(__two); }
  457. template<typename _Alloc>
  458. inline void __do_alloc_on_move(_Alloc&, _Alloc&, false_type)
  459. { }
  460. template<typename _Alloc>
  461. inline void __alloc_on_move(_Alloc& __one, _Alloc& __two)
  462. {
  463. typedef allocator_traits<_Alloc> __traits;
  464. typedef typename __traits::propagate_on_container_move_assignment __pocma;
  465. __do_alloc_on_move(__one, __two, __pocma());
  466. }
  467. template<typename _Alloc>
  468. inline void __do_alloc_on_swap(_Alloc& __one, _Alloc& __two, true_type)
  469. {
  470. using std::swap;
  471. swap(__one, __two);
  472. }
  473. template<typename _Alloc>
  474. inline void __do_alloc_on_swap(_Alloc&, _Alloc&, false_type)
  475. { }
  476. template<typename _Alloc>
  477. inline void __alloc_on_swap(_Alloc& __one, _Alloc& __two)
  478. {
  479. typedef allocator_traits<_Alloc> __traits;
  480. typedef typename __traits::propagate_on_container_swap __pocs;
  481. __do_alloc_on_swap(__one, __two, __pocs());
  482. }
  483. template<typename _Alloc>
  484. class __is_copy_insertable_impl
  485. {
  486. typedef allocator_traits<_Alloc> _Traits;
  487. template<typename _Up, typename
  488. = decltype(_Traits::construct(std::declval<_Alloc&>(),
  489. std::declval<_Up*>(),
  490. std::declval<const _Up&>()))>
  491. static true_type
  492. _M_select(int);
  493. template<typename _Up>
  494. static false_type
  495. _M_select(...);
  496. public:
  497. typedef decltype(_M_select<typename _Alloc::value_type>(0)) type;
  498. };
  499. // true if _Alloc::value_type is CopyInsertable into containers using _Alloc
  500. template<typename _Alloc>
  501. struct __is_copy_insertable
  502. : __is_copy_insertable_impl<_Alloc>::type
  503. { };
  504. // std::allocator<_Tp> just requires CopyConstructible
  505. template<typename _Tp>
  506. struct __is_copy_insertable<allocator<_Tp>>
  507. : is_copy_constructible<_Tp>
  508. { };
  509. // Trait to detect Allocator-like types.
  510. template<typename _Alloc, typename = void>
  511. struct __is_allocator : false_type { };
  512. template<typename _Alloc>
  513. struct __is_allocator<_Alloc,
  514. __void_t<typename _Alloc::value_type,
  515. decltype(std::declval<_Alloc&>().allocate(size_t{}))>>
  516. : true_type { };
  517. template<typename _Alloc>
  518. using _RequireAllocator
  519. = typename enable_if<__is_allocator<_Alloc>::value, _Alloc>::type;
  520. _GLIBCXX_END_NAMESPACE_VERSION
  521. } // namespace std
  522. #endif // C++11
  523. #endif // _ALLOC_TRAITS_H