map 8.9 KB

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