map 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. #ifndef __GBLIBCPP_MAP__
  2. #define __GBLIBCPP_MAP__
  3. #include <bits/iter_ops>
  4. #include <bits/rbtree>
  5. #include <functional>
  6. #include <memory>
  7. #include <initializer_list>
  8. #include <tuple>
  9. #include <type_traits>
  10. #include <utility>
  11. #include <cstddef>
  12. namespace std {
  13. template <typename Key, typename T,
  14. typename Compare = std::less<Key>,
  15. typename Allocator = std::allocator<std::pair<const Key, T>>>
  16. class map {
  17. public:
  18. using key_type = Key;
  19. using mapped_type = T;
  20. using value_type = std::pair<const Key, T>;
  21. using size_type = std::size_t;
  22. using allocator_type = Allocator;
  23. private:
  24. class value_compare : public Compare {
  25. protected:
  26. constexpr value_compare(Compare c): Compare{c} {}
  27. friend class map;
  28. public:
  29. constexpr bool operator()(
  30. const value_type& lhs, const value_type& rhs) const
  31. { return Compare::operator()(lhs.first, rhs.first); }
  32. constexpr bool operator()(
  33. const Key& lhs, const value_type& rhs) const
  34. { return Compare::operator()(lhs, rhs.first); }
  35. constexpr bool operator()(
  36. const value_type& lhs, const Key& rhs) const
  37. { return Compare::operator()(lhs.first, rhs); }
  38. };
  39. using rbtree_type = impl::rbtree<value_type, value_compare, Allocator>;
  40. using node_allocator = typename rbtree_type::node_allocator;
  41. private:
  42. rbtree_type tree;
  43. public:
  44. using iterator = typename rbtree_type::iterator;
  45. using const_iterator = typename rbtree_type::const_iterator;
  46. public:
  47. __GBLIBCPP_CONSTEXPR
  48. iterator end(void) noexcept { return tree.end(); }
  49. __GBLIBCPP_CONSTEXPR
  50. const_iterator end(void) const noexcept { return tree.cend(); }
  51. __GBLIBCPP_CONSTEXPR
  52. const_iterator cend(void) const noexcept { return tree.cend(); }
  53. __GBLIBCPP_CONSTEXPR
  54. iterator begin(void) noexcept { return tree.begin(); }
  55. __GBLIBCPP_CONSTEXPR
  56. const_iterator begin(void) const noexcept { return tree.cbegin(); }
  57. __GBLIBCPP_CONSTEXPR
  58. const_iterator cbegin(void) const noexcept { return tree.cbegin(); }
  59. explicit __GBLIBCPP_CONSTEXPR
  60. map(const Compare& comp,
  61. const Allocator& alloc = Allocator())
  62. : tree(comp, alloc) {}
  63. explicit __GBLIBCPP_CONSTEXPR
  64. map(const Allocator& alloc)
  65. : map(Compare(), alloc) {}
  66. __GBLIBCPP_CONSTEXPR
  67. map() : map(Compare()) {}
  68. template <typename InputIter>
  69. __GBLIBCPP_CONSTEXPR
  70. map(InputIter first, InputIter last,
  71. const Compare& comp = Compare(),
  72. const Allocator& alloc = Allocator())
  73. : map(comp, alloc)
  74. {
  75. insert(first, last);
  76. }
  77. template <typename InputIter>
  78. __GBLIBCPP_CONSTEXPR
  79. map(InputIter first, InputIter last,
  80. const Allocator& alloc = Allocator())
  81. : map(first, last, Compare(), alloc) {}
  82. __GBLIBCPP_CONSTEXPR
  83. map(const map& other) : tree(other.tree) {}
  84. __GBLIBCPP_CONSTEXPR
  85. map(const map& other, const Allocator& alloc)
  86. : tree(other.tree, alloc) { }
  87. __GBLIBCPP_CONSTEXPR
  88. map(map&& other) : tree(std::move(other.tree)) {}
  89. __GBLIBCPP_CONSTEXPR
  90. map(map&& other, const Allocator& alloc)
  91. : tree(std::move(other.tree), alloc) {}
  92. __GBLIBCPP_CONSTEXPR
  93. map(std::initializer_list<value_type> init,
  94. const Compare& comp = Compare(),
  95. const Allocator& alloc = Allocator())
  96. : map(comp, alloc)
  97. { insert(init.begin(), init.end()); }
  98. __GBLIBCPP_CONSTEXPR
  99. map(std::initializer_list<value_type> init,
  100. const Allocator& alloc)
  101. : map(init, Compare(), alloc) {}
  102. __GBLIBCPP_CONSTEXPR
  103. ~map() { clear(); }
  104. __GBLIBCPP_CONSTEXPR
  105. map& operator=(const map& other) = default;
  106. __GBLIBCPP_CONSTEXPR
  107. map& operator=(map&& other) = default;
  108. __GBLIBCPP_CONSTEXPR
  109. map& operator=(std::initializer_list<value_type> ilist)
  110. {
  111. clear();
  112. insert(ilist.begin(), ilist.end());
  113. return *this;
  114. }
  115. __GBLIBCPP_CONSTEXPR
  116. iterator find(const Key& key) { return tree.find(key); }
  117. __GBLIBCPP_CONSTEXPR
  118. const_iterator find(const Key& key) const { return tree.find(key); }
  119. // if the container does not have an element with
  120. // the specified key, it should throw an exception
  121. // TODO: exceptions
  122. __GBLIBCPP_CONSTEXPR
  123. T& at(const Key& key) { return find(key)->second; }
  124. // if the container does not have an element with
  125. // the specified key, it should throw an exception
  126. // TODO: exceptions
  127. __GBLIBCPP_CONSTEXPR
  128. const T& at(const Key& key) const { return find(key)->second; }
  129. __GBLIBCPP_CONSTEXPR
  130. std::pair<iterator, bool> insert(const value_type& value)
  131. { return tree.insert(value); }
  132. __GBLIBCPP_CONSTEXPR
  133. std::pair<iterator, bool> insert(value_type&& value)
  134. { return tree.insert(std::move(value)); }
  135. template <typename Pair>
  136. __GBLIBCPP_CONSTEXPR
  137. std::enable_if_t<std::is_constructible_v<value_type, Pair&&>,
  138. std::pair<iterator, bool>> insert(Pair&& p)
  139. { return emplace(std::forward<Pair>(p)); }
  140. template <typename InputIter>
  141. __GBLIBCPP_CONSTEXPR
  142. void insert(InputIter first, InputIter last)
  143. {
  144. for ( ; first != last; ++first)
  145. insert(*first);
  146. }
  147. template <typename... Args>
  148. __GBLIBCPP_CONSTEXPR
  149. std::pair<iterator, bool> emplace(Args&&... args)
  150. { return tree.emplace(std::forward<Args>(args)...); }
  151. template <typename... Args>
  152. __GBLIBCPP_CONSTEXPR
  153. std::pair<iterator, bool> try_emplace(const Key& key, Args&&... args)
  154. {
  155. auto iter = find(key);
  156. if (iter)
  157. return { iter, false };
  158. return emplace(
  159. std::piecewise_construct,
  160. std::forward_as_tuple(key),
  161. std::forward_as_tuple(std::forward<Args>(args)...));
  162. }
  163. template <typename... Args>
  164. __GBLIBCPP_CONSTEXPR
  165. std::pair<iterator, bool> try_emplace(Key&& key, Args&&... args)
  166. {
  167. auto iter = find(key);
  168. if (iter)
  169. return { iter, false };
  170. return emplace(
  171. std::piecewise_construct,
  172. std::forward_as_tuple(std::move(key)),
  173. std::forward_as_tuple(std::forward<Args>(args)...));
  174. }
  175. __GBLIBCPP_CONSTEXPR
  176. T& operator[](const Key& key)
  177. { return try_emplace(key).first->second; }
  178. __GBLIBCPP_CONSTEXPR
  179. T& operator[](Key&& key)
  180. { return try_emplace(std::move(key)).first->second; }
  181. __GBLIBCPP_CONSTEXPR
  182. iterator erase(iterator pos) noexcept { return tree.erase(pos); }
  183. __GBLIBCPP_CONSTEXPR
  184. iterator erase(const_iterator pos) noexcept { return tree.erase(pos); }
  185. __GBLIBCPP_CONSTEXPR
  186. iterator erase(const_iterator first, const_iterator last) noexcept
  187. {
  188. while (first != last)
  189. first = erase(first);
  190. return first;
  191. }
  192. __GBLIBCPP_CONSTEXPR
  193. size_type erase(const Key& key)
  194. {
  195. auto iter = find(key);
  196. if (!iter)
  197. return 0;
  198. erase(iter);
  199. return 1;
  200. }
  201. __GBLIBCPP_CONSTEXPR
  202. void clear() noexcept { tree.destroy(); }
  203. __GBLIBCPP_CONSTEXPR
  204. bool empty() const noexcept { return tree.empty(); }
  205. __GBLIBCPP_CONSTEXPR
  206. size_type size() const noexcept { return tree.size(); }
  207. __GBLIBCPP_CONSTEXPR
  208. void swap(map& other) { tree.swap(other.tree); }
  209. __GBLIBCPP_CONSTEXPR
  210. size_type count(const Key& key) const
  211. { return find(key) ? 1 : 0; }
  212. __GBLIBCPP_CONSTEXPR
  213. bool contains(const Key& key) const { return count(key) != 0; }
  214. __GBLIBCPP_CONSTEXPR
  215. iterator upper_bound(const Key& key)
  216. { return tree.upper_bound(key); }
  217. __GBLIBCPP_CONSTEXPR
  218. const_iterator upper_bound(const Key& key) const
  219. { return tree.upper_bound(key); }
  220. __GBLIBCPP_CONSTEXPR
  221. iterator lower_bound(const Key& key)
  222. { return tree.lower_bound(key); }
  223. __GBLIBCPP_CONSTEXPR
  224. const_iterator lower_bound(const Key& key) const
  225. { return tree.lower_bound(key); }
  226. };
  227. template <typename Key, typename T, typename Compare, typename Allocator>
  228. void swap(std::map<Key, T, Compare, Allocator>& lhs,
  229. std::map<Key, T, Compare, Allocator>& rhs)
  230. { lhs.swap(rhs); }
  231. template <typename Key, typename T,
  232. typename Compare, typename Allocator, typename Pred>
  233. typename std::map<Key, T, Compare, Allocator>::size_type
  234. erase_if(std::map<Key, T, Compare, Allocator>& c, Pred pred)
  235. {
  236. auto iter = c.begin();
  237. typename std::map<Key, T, Compare, Allocator>::size_type count = 0;
  238. while (iter != c.end()) {
  239. if (pred(*iter)) {
  240. iter = c.erase(iter);
  241. ++count;
  242. } else
  243. ++iter;
  244. }
  245. return count;
  246. }
  247. template <typename Key, typename T,
  248. typename Compare = std::less<Key>,
  249. typename Allocator = std::allocator<std::pair<const Key, T>>>
  250. map(std::initializer_list<std::pair<Key, T>>,
  251. Compare = Compare(), Allocator = Allocator())
  252. -> map<Key, T, Compare, Allocator>;
  253. template <typename Key, typename T, typename Allocator>
  254. map(std::initializer_list<std::pair<Key, T>>, Allocator)
  255. -> map<Key, T, std::less<Key>, Allocator>;
  256. } // namespace std
  257. #endif