memory 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764
  1. #ifndef __GBLIBCPP_MEMORY__
  2. #define __GBLIBCPP_MEMORY__
  3. #include <bits/compressed_pair>
  4. #include <cstddef>
  5. #include <new>
  6. #include <type_traits>
  7. #include <utility>
  8. namespace std {
  9. template <typename T>
  10. constexpr T* addressof(T& arg) noexcept
  11. {
  12. return __builtin_addressof(arg);
  13. }
  14. // template <typename T>
  15. // constexpr enable_if_t<is_function_v<remove_reference_t<T>>, T*>
  16. // addressof(T& arg) noexcept
  17. // {
  18. // return &arg;
  19. // }
  20. // template <typename T>
  21. // constexpr enable_if_t<!is_function_v<remove_reference_t<T>>, T*>
  22. // addressof(T& arg) noexcept
  23. // {
  24. // return reinterpret_cast<T*>(
  25. // &const_cast<char&>(
  26. // reinterpret_cast<const volatile char&>(arg)
  27. // )
  28. // );
  29. // }
  30. template <typename T>
  31. const T* addressof(const T&&) = delete;
  32. namespace __helpers {
  33. template <typename Ptr, typename = void>
  34. struct pointer_difference_type
  35. { using type = std::ptrdiff_t; };
  36. template <typename Ptr>
  37. struct pointer_difference_type<Ptr,
  38. std::void_t<typename Ptr::difference_type>>
  39. { using type = typename Ptr::difference_type; };
  40. template <typename Ptr>
  41. using pointer_difference_type_t =
  42. typename pointer_difference_type<Ptr>::type;
  43. template <typename Base, typename T>
  44. struct rebind;
  45. template <template <typename, typename...> typename Template,
  46. typename NewType, typename OldType, typename... Args>
  47. struct rebind<Template<OldType, Args...>, NewType> {
  48. using type = Template<NewType, Args...>;
  49. };
  50. template <typename Ptr, typename T, typename = void>
  51. struct try_rebind { using type = typename rebind<Ptr, T>::type; };
  52. template <typename Ptr, typename T>
  53. struct try_rebind<Ptr, T,
  54. std::void_t<typename Ptr::template rebind<T>>> {
  55. using type = typename Ptr::template rebind<T>;
  56. };
  57. template <typename Ptr, typename = void>
  58. struct pointer_element {};
  59. template <typename Ptr>
  60. struct pointer_element<Ptr, std::enable_if_t<
  61. std::is_same_v<void, std::void_t<typename Ptr::element_type>>
  62. >> { using type = typename Ptr::element_type; };
  63. template <template <typename, typename...> typename Template,
  64. typename T, typename... Args>
  65. struct pointer_element<Template<T, Args...>, void>
  66. { using type = T; };
  67. template <typename Ptr, typename = void>
  68. struct pointer_traits_impl {};
  69. template <typename Ptr>
  70. struct pointer_traits_impl<Ptr,
  71. std::void_t<typename pointer_element<Ptr>::type>> {
  72. using pointer = Ptr;
  73. using element_type = typename pointer_element<Ptr>::type;
  74. using difference_type = pointer_difference_type_t<Ptr>;
  75. template <typename U>
  76. using rebind = typename try_rebind<Ptr, U>::type;
  77. static pointer pointer_to(element_type& ref)
  78. { return Ptr::pointer_to(ref); }
  79. };
  80. template <typename T>
  81. struct pointer_traits_impl<T*, void> {
  82. using pointer = T*;
  83. using element_type = T;
  84. using difference_type = std::ptrdiff_t;
  85. template <typename U>
  86. using rebind = U*;
  87. static pointer pointer_to(element_type& ref)
  88. { return std::addressof(ref); }
  89. };
  90. } // namespace __helpers
  91. template <typename Ptr>
  92. struct pointer_traits : public __helpers::pointer_traits_impl<Ptr> {};
  93. namespace __helpers {
  94. template <typename Alloc, typename = void>
  95. struct allocator_pointer
  96. { using type = typename Alloc::value_type*; };
  97. template <typename Alloc>
  98. struct allocator_pointer<Alloc,
  99. std::void_t<typename Alloc::pointer>>
  100. { using type = typename Alloc::pointer; };
  101. template <typename Alloc>
  102. using allocator_pointer_t =
  103. typename allocator_pointer<Alloc>::type;
  104. template <typename Alloc, typename Pointer, typename = void>
  105. struct allocator_const_pointer {
  106. using type = typename std::pointer_traits<Pointer>::template
  107. rebind<const typename Alloc::value_type>;
  108. };
  109. template <typename Alloc, typename Pointer>
  110. struct allocator_const_pointer<Alloc, Pointer,
  111. std::void_t<typename Alloc::const_pointer>>
  112. { using type = typename Alloc::const_pointer; };
  113. template <typename Alloc, typename Pointer>
  114. using allocator_const_pointer_t =
  115. typename allocator_const_pointer<Alloc, Pointer>::type;
  116. template <typename Alloc, typename Pointer, typename = void>
  117. struct allocator_void_pointer {
  118. using type = typename std::pointer_traits<Pointer>::template
  119. rebind<void>;
  120. };
  121. template <typename Alloc, typename Pointer>
  122. struct allocator_void_pointer<Alloc, Pointer,
  123. std::void_t<typename Alloc::void_pointer>>
  124. { using type = typename Alloc::void_pointer; };
  125. template <typename Alloc, typename Pointer>
  126. using allocator_void_pointer_t =
  127. typename allocator_void_pointer<Alloc, Pointer>::type;
  128. template <typename Alloc, typename Pointer, typename = void>
  129. struct allocator_const_void_pointer {
  130. using type = typename std::pointer_traits<Pointer>::template
  131. rebind<const void>;
  132. };
  133. template <typename Alloc, typename Pointer>
  134. struct allocator_const_void_pointer<Alloc, Pointer,
  135. std::void_t<typename Alloc::const_void_pointer>>
  136. { using type = typename Alloc::const_void_pointer; };
  137. template <typename Alloc, typename Pointer>
  138. using allocator_const_void_pointer_t =
  139. typename allocator_const_void_pointer<Alloc, Pointer>::type;
  140. template <typename Alloc, typename = void>
  141. struct allocator_difference_type
  142. { using type = std::ptrdiff_t; };
  143. template <typename Alloc>
  144. struct allocator_difference_type<Alloc,
  145. std::void_t<typename Alloc::difference_type>>
  146. { using type = typename Alloc::difference_type; };
  147. template <typename Alloc>
  148. using allocator_difference_type_t =
  149. typename allocator_difference_type<Alloc>::type;
  150. template <typename Alloc, typename = void>
  151. struct allocator_size_type
  152. { using type = std::size_t; };
  153. template <typename Alloc>
  154. struct allocator_size_type<Alloc,
  155. std::void_t<typename Alloc::size_type>>
  156. { using type = typename Alloc::size_type; };
  157. template <typename Alloc>
  158. using allocator_size_type_t =
  159. typename allocator_size_type<Alloc>::type;
  160. template <typename Alloc, typename = void>
  161. struct allocator_prop_copy
  162. { using type = std::false_type; };
  163. template <typename Alloc>
  164. struct allocator_prop_copy<Alloc,
  165. std::void_t<typename Alloc::propagate_on_container_copy_assignment>>
  166. { using type = typename Alloc::propagate_on_container_copy_assignment; };
  167. template <typename Alloc>
  168. using allocator_prop_copy_t =
  169. typename allocator_prop_copy<Alloc>::type;
  170. template <typename Alloc, typename = void>
  171. struct allocator_prop_move
  172. { using type = std::false_type; };
  173. template <typename Alloc>
  174. struct allocator_prop_move<Alloc,
  175. std::void_t<typename Alloc::propagate_on_container_move_assignment>>
  176. { using type = typename Alloc::propagate_on_container_move_assignment; };
  177. template <typename Alloc>
  178. using allocator_prop_move_t =
  179. typename allocator_prop_move<Alloc>::type;
  180. template <typename Alloc, typename = void>
  181. struct allocator_prop_swap
  182. { using type = std::false_type; };
  183. template <typename Alloc>
  184. struct allocator_prop_swap<Alloc,
  185. std::void_t<typename Alloc::propagate_on_container_swap>>
  186. { using type = typename Alloc::propagate_on_container_swap; };
  187. template <typename Alloc>
  188. using allocator_prop_swap_t =
  189. typename allocator_prop_swap<Alloc>::type;
  190. template <typename Alloc, typename = void>
  191. struct is_always_equal
  192. { using type = std::false_type; };
  193. template <typename Alloc>
  194. struct is_always_equal<Alloc,
  195. std::void_t<typename Alloc::is_always_equal>>
  196. { using type = typename Alloc::is_always_equal; };
  197. template <typename Alloc>
  198. using is_always_equal_t =
  199. typename is_always_equal<Alloc>::type;
  200. template <typename Alloc, typename = void>
  201. struct allocator_select_on_copy {
  202. static constexpr Alloc get(const Alloc& alloc)
  203. { return alloc; }
  204. };
  205. template <typename Alloc>
  206. struct allocator_select_on_copy<Alloc, std::enable_if_t<
  207. std::is_same_v<void, std::void_t<decltype(
  208. std::declval<Alloc>().select_on_container_copy_construction()
  209. )>> >> {
  210. static constexpr Alloc get(const Alloc& alloc)
  211. { return alloc.select_on_container_copy_construction(); }
  212. };
  213. template <typename Allocator, typename T, typename = void>
  214. struct allocator_rebind_type {
  215. using type = typename rebind<Allocator, T>::type;
  216. };
  217. template <typename Allocator, typename T>
  218. struct allocator_rebind_type<Allocator, T, std::void_t<
  219. typename Allocator::template rebind<T>::other
  220. >> {
  221. using type = typename Allocator::template rebind<T>::other;
  222. };
  223. } // namespace __helpers
  224. template <typename T>
  225. struct allocator {
  226. using value_type = T;
  227. using propagate_on_container_move_assignment = std::true_type;
  228. constexpr allocator() noexcept = default;
  229. constexpr allocator(const allocator& other) noexcept = default;
  230. template <typename U>
  231. constexpr allocator(const allocator<U>&) noexcept {}
  232. constexpr ~allocator() = default;
  233. // throws std::bad_alloc
  234. [[nodiscard]] constexpr T* allocate(std::size_t n)
  235. { return static_cast<T*>(::operator new(n * sizeof(T))); }
  236. // TODO: check allocated size
  237. constexpr void deallocate(T* ptr, std::size_t)
  238. { ::operator delete(ptr); }
  239. };
  240. template <typename T1, typename T2>
  241. constexpr bool operator==(const allocator<T1>&, const allocator<T2>&) noexcept
  242. { return true; }
  243. template <typename T, typename... Args>
  244. constexpr std::enable_if_t<std::is_same_v<T*,
  245. decltype(::new(std::declval<void*>()) T(std::declval<Args>()...))> , T*>
  246. construct_at(T* p, Args&&... args)
  247. {
  248. return ::new (static_cast<void*>(p)) T(std::forward<Args>(args)...);
  249. }
  250. template <typename T>
  251. constexpr void destroy_at(T* p)
  252. {
  253. // TODO: destroy array
  254. p->~T();
  255. }
  256. template <typename Allocator>
  257. struct allocator_traits {
  258. using allocator_type = Allocator;
  259. using value_type = typename Allocator::value_type;
  260. using pointer =
  261. __helpers::allocator_pointer_t<Allocator>;
  262. using const_pointer =
  263. __helpers::allocator_const_pointer_t<Allocator, pointer>;
  264. using void_pointer =
  265. __helpers::allocator_void_pointer_t<Allocator, pointer>;
  266. using const_void_pointer =
  267. __helpers::allocator_const_void_pointer_t<Allocator, pointer>;
  268. using difference_type =
  269. __helpers::allocator_difference_type_t<Allocator>;
  270. using size_type =
  271. __helpers::allocator_size_type_t<Allocator>;
  272. using propagate_on_container_copy_assignment =
  273. __helpers::allocator_prop_copy_t<Allocator>;
  274. using propagate_on_container_move_assignment =
  275. __helpers::allocator_prop_move_t<Allocator>;
  276. using propagate_on_container_swap =
  277. __helpers::allocator_prop_swap_t<Allocator>;
  278. using is_always_equal =
  279. __helpers::is_always_equal_t<Allocator>;
  280. template <typename T>
  281. using rebind_alloc =
  282. typename __helpers::allocator_rebind_type<Allocator, T>::type;
  283. [[nodiscard]] static constexpr pointer allocate(Allocator& alloc, size_type n)
  284. { return alloc.allocate(n); }
  285. static constexpr void deallocate(Allocator& alloc, pointer p, size_type n)
  286. { return alloc.deallocate(p, n); }
  287. template <typename T, typename... Args>
  288. static constexpr void construct(Allocator&, T* p, Args&&... args)
  289. { std::construct_at(p, std::forward<Args>(args)...); }
  290. template <typename T>
  291. static constexpr void destroy(Allocator&, T* p)
  292. { std::destroy_at(p); }
  293. static constexpr Allocator
  294. select_on_container_copy_construction(const Allocator& alloc)
  295. { return __helpers::allocator_select_on_copy<Allocator>::get(alloc); }
  296. };
  297. // TODO: weak_ptr
  298. template <typename T>
  299. class shared_ptr {
  300. public:
  301. using element_type = std::remove_extent_t<T>;
  302. using pointer = element_type*; // TODO: pointer_traits
  303. using const_pointer = const element_type*;
  304. using reference = element_type&;
  305. using const_reference = const element_type&;
  306. private:
  307. struct control_block_base {
  308. std::size_t ref_count;
  309. std::size_t weak_count;
  310. pointer ptr;
  311. constexpr control_block_base(std::size_t ref_count,
  312. std::size_t weak_count, pointer ptr)
  313. : ref_count(ref_count)
  314. , weak_count(weak_count)
  315. , ptr(ptr)
  316. {
  317. }
  318. virtual constexpr ~control_block_base() = default;
  319. virtual constexpr void do_delete() = 0;
  320. // template <typename U, std::enable_if_t<std::is_convertible_v<T*, U*>, bool> = true>
  321. // constexpr operator typename shared_ptr<U>::control_block_base*() const
  322. // {
  323. // return this;
  324. // }
  325. };
  326. template <typename Deleter>
  327. struct control_block : public virtual control_block_base {
  328. Deleter deleter;
  329. virtual constexpr ~control_block() = default;
  330. template <typename UDeleter>
  331. constexpr control_block(std::size_t ref_count,
  332. std::size_t weak_count, pointer ptr, UDeleter&& deleter)
  333. : control_block_base { ref_count, weak_count, ptr }
  334. , deleter(std::forward<UDeleter>(deleter))
  335. {
  336. }
  337. virtual constexpr void do_delete() override
  338. {
  339. if (this->ptr)
  340. deleter(this->ptr);
  341. this->ptr = nullptr;
  342. }
  343. };
  344. struct default_control_block : public virtual control_block_base {
  345. virtual constexpr ~default_control_block() = default;
  346. constexpr default_control_block(std::size_t ref_count,
  347. std::size_t weak_count, pointer ptr)
  348. : control_block_base { ref_count, weak_count, ptr }
  349. {
  350. }
  351. virtual constexpr void do_delete() override
  352. {
  353. if (this->ptr)
  354. delete this->ptr;
  355. this->ptr = nullptr;
  356. }
  357. };
  358. control_block_base* cb {};
  359. pointer ptr {};
  360. void inc_ref()
  361. {
  362. if (cb)
  363. ++cb->ref_count; // TODO: lock and atomic
  364. }
  365. void dec_ref()
  366. {
  367. if (cb && --cb->ref_count == 0) {
  368. cb->do_delete();
  369. if (cb->weak_count == 0)
  370. delete cb;
  371. }
  372. }
  373. private:
  374. template <typename Deleter>
  375. using rebind_allocator = typename std::allocator_traits<Deleter>::template rebind_alloc<control_block<Deleter>>;
  376. template <typename U>
  377. friend class shared_ptr;
  378. public:
  379. __GBLIBCPP_CONSTEXPR shared_ptr() noexcept = default;
  380. __GBLIBCPP_CONSTEXPR shared_ptr(std::nullptr_t) noexcept { }
  381. template <typename U, enable_if_t<is_convertible_v<U*, T*>, bool> = true>
  382. __GBLIBCPP_CONSTEXPR explicit shared_ptr(U* p) // TODO: array type
  383. : cb(new default_control_block { 1, 0, p })
  384. , ptr(p)
  385. {
  386. }
  387. template <typename U, typename Deleter, enable_if_t<is_convertible_v<U*, T*>, bool> = true>
  388. __GBLIBCPP_CONSTEXPR explicit shared_ptr(U* p, Deleter d)
  389. : cb(new control_block<Deleter> { 1, 0, p, d })
  390. , ptr(p)
  391. {
  392. }
  393. template <typename Deleter>
  394. __GBLIBCPP_CONSTEXPR explicit shared_ptr(std::nullptr_t, Deleter d)
  395. : cb(new control_block<Deleter> { 1, 0, nullptr, d })
  396. {
  397. }
  398. template <typename U, typename Deleter, typename Allocator,
  399. enable_if_t<is_convertible_v<U*, T*>, bool> = true>
  400. __GBLIBCPP_CONSTEXPR explicit shared_ptr(U* p, Deleter d, Allocator alloc)
  401. {
  402. cb = std::allocator_traits<
  403. rebind_allocator<Deleter>>::allocate(alloc, 1);
  404. std::allocator_traits<
  405. rebind_allocator<Deleter>>::construct(alloc, cb, 1, 0, p, d);
  406. ptr = p;
  407. }
  408. template <typename Deleter, typename Allocator>
  409. __GBLIBCPP_CONSTEXPR explicit shared_ptr(std::nullptr_t, Deleter d, Allocator alloc)
  410. {
  411. cb = std::allocator_traits<
  412. rebind_allocator<Deleter>>::allocate(alloc, 1);
  413. std::allocator_traits<
  414. rebind_allocator<Deleter>>::construct(alloc, cb, 1, 0, nullptr, d);
  415. }
  416. __GBLIBCPP_CONSTEXPR
  417. shared_ptr(const shared_ptr& other) noexcept
  418. : cb(other.cb)
  419. , ptr(other.ptr)
  420. {
  421. inc_ref();
  422. }
  423. __GBLIBCPP_CONSTEXPR
  424. shared_ptr(shared_ptr&& other) noexcept
  425. : cb(std::exchange(other.cb, nullptr))
  426. , ptr(std::exchange(other.ptr, nullptr))
  427. {
  428. }
  429. template <typename U, enable_if_t<is_convertible_v<U*, T*>, bool> = true>
  430. __GBLIBCPP_CONSTEXPR
  431. shared_ptr(const shared_ptr<U>& other) noexcept
  432. : cb((control_block_base*)other.cb)
  433. , ptr((T*)other.ptr)
  434. {
  435. inc_ref();
  436. }
  437. template <typename U, enable_if_t<is_convertible_v<U*, T*>, bool> = true>
  438. __GBLIBCPP_CONSTEXPR
  439. shared_ptr(shared_ptr<U>&& other) noexcept
  440. : cb((control_block_base*)std::exchange(other.cb, nullptr))
  441. , ptr((T*)std::exchange(other.ptr, nullptr))
  442. {
  443. }
  444. // TODO: weak_ptr and unique_ptr
  445. __GBLIBCPP_CONSTEXPR
  446. ~shared_ptr()
  447. {
  448. dec_ref();
  449. cb = nullptr;
  450. ptr = nullptr;
  451. }
  452. __GBLIBCPP_CONSTEXPR
  453. shared_ptr& operator=(const shared_ptr& other) noexcept
  454. {
  455. shared_ptr { other }.swap(*this);
  456. return *this;
  457. }
  458. template <typename U, enable_if_t<is_convertible_v<U*, T*>, bool> = true>
  459. __GBLIBCPP_CONSTEXPR shared_ptr& operator=(const shared_ptr<U>& other) noexcept
  460. {
  461. shared_ptr { other }.swap(*this);
  462. return *this;
  463. }
  464. __GBLIBCPP_CONSTEXPR
  465. shared_ptr& operator=(shared_ptr&& other) noexcept
  466. {
  467. shared_ptr { move(other) }.swap(*this);
  468. return *this;
  469. }
  470. template <typename U, enable_if_t<is_convertible_v<U*, T*>, bool> = true>
  471. __GBLIBCPP_CONSTEXPR shared_ptr& operator=(shared_ptr<U>&& other) noexcept
  472. {
  473. shared_ptr { move(other) }.swap(*this);
  474. return *this;
  475. }
  476. __GBLIBCPP_CONSTEXPR
  477. element_type* get() const noexcept
  478. {
  479. return cb ? ptr : nullptr;
  480. }
  481. __GBLIBCPP_CONSTEXPR
  482. explicit operator bool() const noexcept
  483. {
  484. return get();
  485. }
  486. __GBLIBCPP_CONSTEXPR
  487. T& operator*() const noexcept { return *get(); }
  488. __GBLIBCPP_CONSTEXPR
  489. T* operator->() const noexcept { return get(); }
  490. __GBLIBCPP_CONSTEXPR
  491. element_type& operator[](std::size_t i) const noexcept { return get()[i]; }
  492. __GBLIBCPP_CONSTEXPR
  493. long use_count() const noexcept { return cb ? cb->ref_count : 0; }
  494. __GBLIBCPP_CONSTEXPR
  495. bool owner_before(const shared_ptr& other) const noexcept
  496. {
  497. return cb < other.cb;
  498. }
  499. __GBLIBCPP_CONSTEXPR
  500. void swap(shared_ptr& other) noexcept
  501. {
  502. std::swap(cb, other.cb);
  503. std::swap(ptr, other.ptr);
  504. }
  505. __GBLIBCPP_CONSTEXPR
  506. void reset() noexcept
  507. {
  508. shared_ptr {}.swap(*this);
  509. }
  510. template <typename U, enable_if_t<is_convertible_v<U*, T*>, bool> = true>
  511. __GBLIBCPP_CONSTEXPR void reset(U* p) noexcept
  512. {
  513. shared_ptr { p }.swap(*this);
  514. }
  515. template <typename U, typename Deleter, enable_if_t<is_convertible_v<U*, T*>, bool> = true>
  516. __GBLIBCPP_CONSTEXPR void reset(U* p, Deleter d) noexcept
  517. {
  518. shared_ptr { p, d }.swap(*this);
  519. }
  520. template <typename U, typename Deleter, typename Allocator,
  521. enable_if_t<is_convertible_v<U*, T*>, bool> = true>
  522. __GBLIBCPP_CONSTEXPR void reset(U* p, Deleter d, Allocator alloc)
  523. {
  524. shared_ptr { p, d, alloc }.swap(*this);
  525. }
  526. };
  527. template <typename T>
  528. struct default_delete {
  529. __GBLIBCPP_CONSTEXPR default_delete() noexcept = default;
  530. template <typename U, std::enable_if_t<std::is_convertible_v<U*, T*>, bool> = true>
  531. __GBLIBCPP_CONSTEXPR default_delete(const default_delete<U>&) noexcept {}
  532. __GBLIBCPP_CONSTEXPR void operator()(T* p) const
  533. {
  534. delete p;
  535. }
  536. };
  537. template <typename T, typename Deleter = std::default_delete<T>>
  538. class unique_ptr {
  539. public:
  540. using element_type = T;
  541. using deleter_type = Deleter;
  542. using pointer = element_type*;
  543. private:
  544. impl::compressed_pair<pointer, deleter_type> data;
  545. public:
  546. __GBLIBCPP_CONSTEXPR unique_ptr() noexcept: data{impl::default_construct_t{}} { }
  547. __GBLIBCPP_CONSTEXPR unique_ptr(std::nullptr_t) noexcept: unique_ptr{} { }
  548. __GBLIBCPP_CONSTEXPR unique_ptr(pointer p) noexcept: data{p, deleter_type{}} { }
  549. __GBLIBCPP_CONSTEXPR unique_ptr(pointer p, const deleter_type& d) noexcept: data{p, d} { }
  550. __GBLIBCPP_CONSTEXPR unique_ptr(pointer p, deleter_type&& d) noexcept: data{p, std::move(d)} { }
  551. __GBLIBCPP_CONSTEXPR unique_ptr(const unique_ptr&) = delete;
  552. __GBLIBCPP_CONSTEXPR unique_ptr(unique_ptr&& other) noexcept
  553. : data{std::exchange(other.data.first(), nullptr), std::move(other.data.second())} { }
  554. template <typename U, typename E, std::enable_if_t<
  555. !std::is_array_v<U> && std::is_convertible_v<U*, T*>
  556. && std::is_convertible_v<E, Deleter>, bool> = true>
  557. __GBLIBCPP_CONSTEXPR unique_ptr(unique_ptr<U, E>&& other) noexcept
  558. : data{std::exchange(other.data.first(), nullptr), std::move(other.data.second())} { }
  559. __GBLIBCPP_CONSTEXPR ~unique_ptr() { reset(); }
  560. __GBLIBCPP_CONSTEXPR unique_ptr& operator=(const unique_ptr&) = delete;
  561. __GBLIBCPP_CONSTEXPR unique_ptr& operator=(std::nullptr_t) noexcept
  562. {
  563. reset();
  564. return *this;
  565. }
  566. __GBLIBCPP_CONSTEXPR unique_ptr& operator=(unique_ptr&& other) noexcept
  567. {
  568. reset(other.release());
  569. get_deleter() = std::move(other.get_deleter());
  570. return *this;
  571. }
  572. template <typename U, typename E, std::enable_if_t<
  573. !std::is_array_v<U> && std::is_convertible_v<U*, T*>
  574. && std::is_assignable_v<Deleter&, E&&>, bool> = true>
  575. __GBLIBCPP_CONSTEXPR unique_ptr& operator=(unique_ptr<U, E>&& other) noexcept
  576. {
  577. reset(other.release());
  578. get_deleter() = std::move(other.get_deleter());
  579. return *this;
  580. }
  581. __GBLIBCPP_CONSTEXPR void swap(unique_ptr& other) noexcept
  582. {
  583. std::swap(data, other.data);
  584. }
  585. __GBLIBCPP_CONSTEXPR pointer get() const noexcept { return data.first(); }
  586. __GBLIBCPP_CONSTEXPR deleter_type& get_deleter() noexcept { return data.second(); }
  587. __GBLIBCPP_CONSTEXPR const deleter_type& get_deleter() const noexcept { return data.second(); }
  588. __GBLIBCPP_CONSTEXPR pointer release() noexcept
  589. {
  590. pointer ret = get();
  591. data.first() = nullptr;
  592. return ret;
  593. }
  594. __GBLIBCPP_CONSTEXPR void reset(pointer p = pointer{}) noexcept
  595. {
  596. pointer old = release();
  597. data.first() = p;
  598. if (old)
  599. get_deleter()(old);
  600. }
  601. __GBLIBCPP_CONSTEXPR explicit operator bool() const noexcept { return get(); }
  602. __GBLIBCPP_CONSTEXPR pointer operator->() const noexcept { return get(); }
  603. __GBLIBCPP_CONSTEXPR std::add_lvalue_reference_t<T> operator*() const
  604. noexcept(noexcept(*std::declval<pointer>())) { return *get(); }
  605. };
  606. // TODO: use only one allocation
  607. template <typename T, typename... Args>
  608. std::shared_ptr<T> make_shared(Args&&... args)
  609. {
  610. return std::shared_ptr<T>(new T(std::forward<Args>(args)...));
  611. }
  612. template <typename T, typename... Args>
  613. __GBLIBCPP_CONSTEXPR std::unique_ptr<T> make_unique(Args&&... args)
  614. {
  615. return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
  616. }
  617. template <typename T>
  618. __GBLIBCPP_CONSTEXPR void swap(std::shared_ptr<T>& lhs, std::shared_ptr<T>& rhs) noexcept
  619. {
  620. lhs.swap(rhs);
  621. }
  622. template <typename T, typename D>
  623. __GBLIBCPP_CONSTEXPR void swap(std::unique_ptr<T, D>& lhs, std::unique_ptr<T, D>& rhs) noexcept
  624. {
  625. lhs.swap(rhs);
  626. }
  627. } // namespace std
  628. #endif