list 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. #ifndef __GBLIBCPP_LIST__
  2. #define __GBLIBCPP_LIST__
  3. #include <bits/compressed_pair>
  4. #include <bits/iter_ops>
  5. #include <memory>
  6. #include <initializer_list>
  7. #include <type_traits>
  8. #include <utility>
  9. #include <cstddef>
  10. namespace std {
  11. template <typename T, typename Allocator = std::allocator<T>>
  12. class list {
  13. private:
  14. struct node_base {
  15. node_base* prev;
  16. node_base* next;
  17. constexpr node_base() noexcept
  18. : prev { this }, next { this } {}
  19. constexpr void connect(node_base* _next) noexcept
  20. {
  21. this->next = _next;
  22. _next->prev = static_cast<node_base*>(this);
  23. }
  24. constexpr void swap(node_base& other) noexcept
  25. {
  26. std::swap(prev, other.prev);
  27. std::swap(next, other.next);
  28. }
  29. };
  30. struct node : public node_base {
  31. T value;
  32. template <typename... Args>
  33. explicit constexpr node(Args&&... args)
  34. : value(std::forward<Args>(args)...) { }
  35. };
  36. public:
  37. template <bool Const>
  38. class _iterator;
  39. public:
  40. using value_type = T;
  41. using allocator_type = Allocator;
  42. using size_type = std::size_t;
  43. using difference_type = std::ptrdiff_t;
  44. using reference = T&;
  45. using const_reference = const T&;
  46. using pointer = typename std::allocator_traits<Allocator>::pointer;
  47. using const_pointer = typename
  48. std::allocator_traits<Allocator>::const_pointer;
  49. using iterator = _iterator<false>;
  50. using const_iterator = _iterator<true>;
  51. private:
  52. using alloc_traits = std::allocator_traits<allocator_type>;
  53. using node_alloc_type = typename
  54. std::allocator_traits<Allocator>::template rebind_alloc<node>;
  55. using node_alloc_traits = std::allocator_traits<node_alloc_type>;
  56. public:
  57. template <bool Const>
  58. class _iterator {
  59. public:
  60. using const_node_pointer = const node_base*;
  61. using node_pointer = node_base*;
  62. using value_type = std::conditional_t<Const, const T, T>;
  63. using pointer = std::add_pointer_t<value_type>;
  64. using reference = std::add_lvalue_reference_t<value_type>;
  65. friend class list;
  66. private:
  67. node_pointer p;
  68. public:
  69. constexpr _iterator() noexcept = default;
  70. explicit constexpr _iterator(const_node_pointer p)
  71. : p { const_cast<node_pointer>(p) } {}
  72. constexpr _iterator(const _iterator& iter) noexcept = default;
  73. constexpr _iterator(_iterator&& iter) noexcept = default;
  74. constexpr ~_iterator() = default;
  75. constexpr _iterator& operator=(const _iterator& iter) noexcept = default;
  76. constexpr _iterator& operator=(_iterator&& iter) noexcept = default;
  77. constexpr bool operator==(const _iterator& iter) const noexcept = default;
  78. constexpr reference operator*() const noexcept
  79. { return ((node*)p)->value; }
  80. constexpr pointer operator&() const noexcept
  81. { return std::addressof(this->operator*()); }
  82. constexpr pointer operator->() const noexcept
  83. { return this->operator&(); }
  84. constexpr _iterator& operator++() noexcept
  85. { p = p->next; return *this; }
  86. constexpr _iterator operator++(int) noexcept
  87. { _iterator ret(p); (void)this->operator++(); return ret; }
  88. constexpr _iterator& operator--(void) noexcept
  89. { p = p->prev; return *this; }
  90. constexpr _iterator operator--(int) noexcept
  91. { _iterator ret(p); (void)this->operator--(); return ret; }
  92. constexpr operator bool() const { return p; }
  93. constexpr operator _iterator<true>() const { return _iterator<true> { p }; }
  94. };
  95. private:
  96. node_base m_head;
  97. impl::compressed_pair<size_type, node_alloc_type> m_pair;
  98. private:
  99. // move m_head and m_size of other to *this
  100. // other MUST NOT be empty, *this MUST be empty
  101. constexpr void _move_from(list&& other) noexcept
  102. {
  103. std::swap(_size(), other._size());
  104. other.m_head.prev->connect(&m_head);
  105. m_head.connect(other.m_head.next);
  106. other.m_head.next = other.m_head.prev = &other.m_head;
  107. }
  108. constexpr size_type& _size() noexcept { return m_pair.first(); }
  109. constexpr const size_type& _size() const noexcept { return m_pair.first(); }
  110. constexpr node_alloc_type& _alloc() noexcept { return m_pair.second(); }
  111. constexpr const node_alloc_type& _alloc() const noexcept { return m_pair.second(); }
  112. public:
  113. __GBLIBCPP_CONSTEXPR
  114. iterator end(void) noexcept { return iterator { &m_head }; }
  115. __GBLIBCPP_CONSTEXPR
  116. const_iterator cend(void) const noexcept { return const_iterator { &m_head }; }
  117. __GBLIBCPP_CONSTEXPR
  118. const_iterator end(void) const noexcept { return cend(); }
  119. __GBLIBCPP_CONSTEXPR
  120. iterator begin(void) noexcept { return iterator { m_head.next }; }
  121. __GBLIBCPP_CONSTEXPR
  122. const_iterator cbegin(void) const noexcept
  123. { return const_iterator { m_head.next }; }
  124. __GBLIBCPP_CONSTEXPR
  125. const_iterator begin(void) const noexcept { return cbegin(); }
  126. template <typename... Args>
  127. __GBLIBCPP_CONSTEXPR
  128. iterator emplace(const_iterator pos, Args&&... args)
  129. {
  130. node* nd = node_alloc_traits::allocate(_alloc(), 1);
  131. node_alloc_traits::construct(_alloc(), nd, std::forward<Args>(args)...);
  132. nd->next = pos.p;
  133. nd->prev = pos.p->prev;
  134. nd->next->prev = nd;
  135. nd->prev->next = nd;
  136. ++_size();
  137. return iterator { nd };
  138. }
  139. explicit __GBLIBCPP_CONSTEXPR
  140. list(const Allocator& alloc): m_head{}, m_pair{0, alloc} { }
  141. __GBLIBCPP_CONSTEXPR
  142. list(): list(Allocator()) {}
  143. __GBLIBCPP_CONSTEXPR
  144. explicit list(size_type count, const Allocator& alloc = Allocator()): list(alloc)
  145. {
  146. while (count--)
  147. emplace_back();
  148. }
  149. __GBLIBCPP_CONSTEXPR
  150. list(size_type count, const T& value, const Allocator& alloc = Allocator()): list(alloc)
  151. {
  152. while (count--)
  153. emplace_back(value);
  154. }
  155. template <typename InputIter>
  156. __GBLIBCPP_CONSTEXPR
  157. list(InputIter first, InputIter last, const Allocator& alloc = Allocator())
  158. : list(alloc) { insert(first, last); }
  159. __GBLIBCPP_CONSTEXPR
  160. list(const list& other, const Allocator& alloc): list(alloc)
  161. {
  162. // TODO: select_on_container_copy_construction
  163. for (const auto& item : other)
  164. emplace_back(item);
  165. }
  166. __GBLIBCPP_CONSTEXPR
  167. list(const list& other): list(other,
  168. alloc_traits::select_on_container_copy_construction(_alloc())) { }
  169. __GBLIBCPP_CONSTEXPR
  170. list(list&& other): m_head{}, m_pair{0, std::move(other._alloc())}
  171. {
  172. if (other.empty())
  173. return;
  174. _move_from(std::move(other));
  175. }
  176. __GBLIBCPP_CONSTEXPR
  177. list(list&& other, const Allocator& alloc): m_head{}, m_pair{0, alloc}
  178. {
  179. if (other._alloc() != alloc) {
  180. for (auto iter = other.begin(); iter != other.end(); ++iter)
  181. emplace(cend(), std::move(*iter));
  182. other.clear();
  183. return;
  184. }
  185. // other._alloc() == alloc
  186. if (other.empty())
  187. return;
  188. _move_from(std::move(other));
  189. }
  190. __GBLIBCPP_CONSTEXPR
  191. list(std::initializer_list<T> ilist,
  192. const Allocator& alloc = Allocator())
  193. : list(alloc)
  194. {
  195. for (const auto& item : ilist)
  196. emplace_back(item);
  197. }
  198. __GBLIBCPP_CONSTEXPR
  199. ~list()
  200. {
  201. clear();
  202. m_head.next = m_head.prev = nullptr;
  203. }
  204. __GBLIBCPP_CONSTEXPR
  205. list& operator=(const list& other)
  206. {
  207. // TODO: reuse memory if _alloc() == other._alloc()
  208. clear();
  209. if constexpr (alloc_traits::
  210. propagate_on_container_copy_assignment::value)
  211. _alloc() = other._alloc();
  212. for (const auto& item : other)
  213. emplace_back(item);
  214. return *this;
  215. }
  216. __GBLIBCPP_CONSTEXPR
  217. list& operator=(list&& other)
  218. {
  219. if (alloc_traits::
  220. propagate_on_container_move_assignment::value) {
  221. clear();
  222. _alloc() = std::move(other._alloc());
  223. if (other.empty())
  224. return *this;
  225. _move_from(std::move(other));
  226. return *this;
  227. }
  228. // TODO: reuse memory if _alloc() == other._alloc()
  229. clear();
  230. if (_alloc() != other._alloc()) {
  231. for (auto iter = other.begin(); iter != other.end(); ++iter)
  232. emplace(cend(), std::move(*iter));
  233. other.clear();
  234. return *this;
  235. }
  236. _move_from(std::move(other));
  237. return *this;
  238. }
  239. __GBLIBCPP_CONSTEXPR
  240. list& operator=(std::initializer_list<T> ilist)
  241. {
  242. // TODO: reuse memory
  243. clear();
  244. for (const auto& item : ilist)
  245. emplace_back(item);
  246. return *this;
  247. }
  248. __GBLIBCPP_CONSTEXPR
  249. void assign(size_type count, const T& value)
  250. {
  251. clear();
  252. while (count--)
  253. emplace_back(value);
  254. }
  255. template <typename InputIter>
  256. __GBLIBCPP_CONSTEXPR
  257. void assign(InputIter first, InputIter last)
  258. {
  259. clear();
  260. insert(first, last);
  261. }
  262. __GBLIBCPP_CONSTEXPR
  263. void assign(std::initializer_list<T> ilist)
  264. {
  265. clear();
  266. for (const auto& item : ilist)
  267. emplace_back(item);
  268. }
  269. __GBLIBCPP_CONSTEXPR
  270. allocator_type get_allocator() const noexcept { return _alloc(); }
  271. __GBLIBCPP_CONSTEXPR
  272. reference front() { return *begin(); }
  273. __GBLIBCPP_CONSTEXPR
  274. const_reference front() const { return *cbegin(); }
  275. __GBLIBCPP_CONSTEXPR
  276. reference back() { return *--end(); }
  277. __GBLIBCPP_CONSTEXPR
  278. const_reference back() const { return *--cend(); }
  279. __GBLIBCPP_CONSTEXPR
  280. iterator insert(const_iterator pos, const T& value)
  281. { return emplace(pos, value); }
  282. __GBLIBCPP_CONSTEXPR
  283. iterator insert(const_iterator pos, T&& value)
  284. { return emplace(pos, std::move(value)); }
  285. __GBLIBCPP_CONSTEXPR
  286. iterator insert(const_iterator pos, size_type count, const T& value)
  287. {
  288. if (!(count--))
  289. return pos;
  290. auto ret = insert(pos, value);
  291. while (count--)
  292. insert(pos, value);
  293. return ret;
  294. }
  295. template <typename InputIter>
  296. __GBLIBCPP_CONSTEXPR
  297. void insert(InputIter first, InputIter last)
  298. {
  299. for ( ; first != last; ++first)
  300. emplace_back(*first);
  301. }
  302. template <typename... Args>
  303. __GBLIBCPP_CONSTEXPR
  304. reference emplace_back(Args&&... args)
  305. { return *emplace(end(), std::forward<Args>(args)...); }
  306. template <typename... Args>
  307. __GBLIBCPP_CONSTEXPR
  308. reference emplace_front(Args&&... args)
  309. { return *emplace(begin(), std::forward<Args>(args)...); }
  310. __GBLIBCPP_CONSTEXPR
  311. void push_back(const T& value)
  312. { emplace_back(value); }
  313. __GBLIBCPP_CONSTEXPR
  314. void push_back(T&& value)
  315. { emplace_back(std::move(value)); }
  316. __GBLIBCPP_CONSTEXPR
  317. void push_front(const T& value)
  318. { emplace_front(value); }
  319. __GBLIBCPP_CONSTEXPR
  320. void push_front(T&& value)
  321. { emplace_front(std::move(value)); }
  322. __GBLIBCPP_CONSTEXPR
  323. void pop_back() { erase(--end()); }
  324. __GBLIBCPP_CONSTEXPR
  325. void pop_front() { erase(begin()); }
  326. __GBLIBCPP_CONSTEXPR
  327. iterator erase(const_iterator pos) noexcept
  328. {
  329. iterator ret { pos.p->next };
  330. pos.p->next->prev = pos.p->prev;
  331. pos.p->prev->next = pos.p->next;
  332. node_alloc_traits::destroy(_alloc(), (node*)pos.p);
  333. node_alloc_traits::deallocate(_alloc(), (node*)pos.p, 1);
  334. --_size();
  335. return ret;
  336. }
  337. __GBLIBCPP_CONSTEXPR
  338. iterator erase(const_iterator first, const_iterator last) noexcept
  339. {
  340. while (first != last)
  341. first = erase(first);
  342. return first;
  343. }
  344. __GBLIBCPP_CONSTEXPR
  345. void clear() noexcept
  346. {
  347. for (auto iter = begin(); iter != end(); )
  348. iter = erase(iter);
  349. }
  350. __GBLIBCPP_CONSTEXPR
  351. size_type size() const noexcept { return _size(); }
  352. __GBLIBCPP_CONSTEXPR
  353. bool empty() const noexcept { return size() == 0; }
  354. __GBLIBCPP_CONSTEXPR
  355. void swap(list& other)
  356. {
  357. if constexpr (alloc_traits::propagate_on_container_swap::value)
  358. std::swap(_alloc(), other._alloc());
  359. std::swap(_size(), other.m_size);
  360. std::swap(m_head, other.m_head);
  361. std::swap(m_head.next->prev, other.m_head.next->prev);
  362. std::swap(m_head.prev->next, other.m_head.prev->next);
  363. }
  364. __GBLIBCPP_CONSTEXPR
  365. void resize(size_type count)
  366. {
  367. while (count > size())
  368. emplace_back();
  369. while (count < size())
  370. pop_back();
  371. }
  372. __GBLIBCPP_CONSTEXPR
  373. void resize(size_type count, const value_type& value)
  374. {
  375. while (count > size())
  376. emplace_back(value);
  377. while (count < size())
  378. pop_back();
  379. }
  380. __GBLIBCPP_CONSTEXPR
  381. size_type remove(const T& value)
  382. {
  383. size_type retval = 0;
  384. for (auto iter = begin(); iter != end(); ) {
  385. if (value != *iter) {
  386. ++iter;
  387. continue;
  388. }
  389. ++retval;
  390. iter = erase(iter);
  391. }
  392. return retval;
  393. }
  394. template <typename UnaryPredicate>
  395. __GBLIBCPP_CONSTEXPR
  396. size_type remove_if(UnaryPredicate p)
  397. {
  398. size_type retval = 0;
  399. for (auto iter = begin(); iter != end(); ) {
  400. if (!p(*iter)) {
  401. ++iter;
  402. continue;
  403. }
  404. ++retval;
  405. iter = erase(iter);
  406. }
  407. return retval;
  408. }
  409. };
  410. template <typename T, typename Allocator>
  411. void swap(std::list<T, Allocator>& lhs,
  412. std::list<T, Allocator>& rhs) { lhs.swap(rhs); }
  413. template <typename T, typename Allocator, typename U>
  414. typename std::list<T, Allocator>::size_type
  415. erase(std::list<T, Allocator>& l, const U& value)
  416. {
  417. return l.remove_if([&](auto& elem) { return elem == value; });
  418. }
  419. template <typename T, typename Allocator, typename Predicate>
  420. typename std::list<T, Allocator>::size_type
  421. erase_if(std::list<T, Allocator>& l, Predicate p)
  422. { return l.remove_if(p); }
  423. } // namespace std
  424. #endif