vector 15 KB

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