list 13 KB

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