vector 16 KB

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