vector 15 KB

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