No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

300 líneas
8.0KB

  1. // Node handles for containers -*- C++ -*-
  2. // Copyright (C) 2016-2020 Free Software Foundation, Inc.
  3. //
  4. // This file is part of the GNU ISO C++ Library. This library is free
  5. // software; you can redistribute it and/or modify it under the
  6. // terms of the GNU General Public License as published by the
  7. // Free Software Foundation; either version 3, or (at your option)
  8. // any later version.
  9. // This library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // Under Section 7 of GPL version 3, you are granted additional
  14. // permissions described in the GCC Runtime Library Exception, version
  15. // 3.1, as published by the Free Software Foundation.
  16. // You should have received a copy of the GNU General Public License and
  17. // a copy of the GCC Runtime Library Exception along with this program;
  18. // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. // <http://www.gnu.org/licenses/>.
  20. /** @file bits/node_handle.h
  21. * This is an internal header file, included by other library headers.
  22. * Do not attempt to use it directly.
  23. * @headername{map,set,unordered_map,unordered_set}
  24. */
  25. #ifndef _NODE_HANDLE
  26. #define _NODE_HANDLE 1
  27. #pragma GCC system_header
  28. #if __cplusplus > 201402L
  29. # define __cpp_lib_node_extract 201606
  30. #include <optional>
  31. #include <bits/alloc_traits.h>
  32. #include <bits/ptr_traits.h>
  33. namespace std _GLIBCXX_VISIBILITY(default)
  34. {
  35. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  36. /// Base class for node handle types of maps and sets.
  37. template<typename _Val, typename _NodeAlloc>
  38. class _Node_handle_common
  39. {
  40. using _AllocTraits = allocator_traits<_NodeAlloc>;
  41. public:
  42. using allocator_type = __alloc_rebind<_NodeAlloc, _Val>;
  43. allocator_type
  44. get_allocator() const noexcept
  45. {
  46. __glibcxx_assert(!this->empty());
  47. return allocator_type(*_M_alloc);
  48. }
  49. explicit operator bool() const noexcept { return _M_ptr != nullptr; }
  50. [[nodiscard]] bool empty() const noexcept { return _M_ptr == nullptr; }
  51. protected:
  52. constexpr _Node_handle_common() noexcept : _M_ptr(), _M_alloc() {}
  53. ~_Node_handle_common() { _M_destroy(); }
  54. _Node_handle_common(_Node_handle_common&& __nh) noexcept
  55. : _M_ptr(__nh._M_ptr), _M_alloc(std::move(__nh._M_alloc))
  56. {
  57. __nh._M_ptr = nullptr;
  58. __nh._M_alloc = nullopt;
  59. }
  60. _Node_handle_common&
  61. operator=(_Node_handle_common&& __nh) noexcept
  62. {
  63. _M_destroy();
  64. _M_ptr = __nh._M_ptr;
  65. if constexpr (is_move_assignable_v<_NodeAlloc>)
  66. {
  67. if (_AllocTraits::propagate_on_container_move_assignment::value
  68. || !this->_M_alloc)
  69. this->_M_alloc = std::move(__nh._M_alloc);
  70. else
  71. {
  72. __glibcxx_assert(this->_M_alloc == __nh._M_alloc);
  73. }
  74. }
  75. else
  76. {
  77. __glibcxx_assert(_M_alloc);
  78. }
  79. __nh._M_ptr = nullptr;
  80. __nh._M_alloc = nullopt;
  81. return *this;
  82. }
  83. _Node_handle_common(typename _AllocTraits::pointer __ptr,
  84. const _NodeAlloc& __alloc)
  85. : _M_ptr(__ptr), _M_alloc(__alloc) { }
  86. void
  87. _M_swap(_Node_handle_common& __nh) noexcept
  88. {
  89. using std::swap;
  90. swap(_M_ptr, __nh._M_ptr);
  91. if (_AllocTraits::propagate_on_container_swap::value
  92. || !_M_alloc || !__nh._M_alloc)
  93. _M_alloc.swap(__nh._M_alloc);
  94. else
  95. {
  96. __glibcxx_assert(_M_alloc == __nh._M_alloc);
  97. }
  98. }
  99. private:
  100. void
  101. _M_destroy() noexcept
  102. {
  103. if (_M_ptr != nullptr)
  104. {
  105. allocator_type __alloc(*_M_alloc);
  106. allocator_traits<allocator_type>::destroy(__alloc,
  107. _M_ptr->_M_valptr());
  108. _AllocTraits::deallocate(*_M_alloc, _M_ptr, 1);
  109. }
  110. }
  111. protected:
  112. typename _AllocTraits::pointer _M_ptr;
  113. private:
  114. optional<_NodeAlloc> _M_alloc;
  115. template<typename _Key2, typename _Value2, typename _KeyOfValue,
  116. typename _Compare, typename _ValueAlloc>
  117. friend class _Rb_tree;
  118. };
  119. /// Node handle type for maps.
  120. template<typename _Key, typename _Value, typename _NodeAlloc>
  121. class _Node_handle : public _Node_handle_common<_Value, _NodeAlloc>
  122. {
  123. public:
  124. constexpr _Node_handle() noexcept = default;
  125. ~_Node_handle() = default;
  126. _Node_handle(_Node_handle&&) noexcept = default;
  127. _Node_handle&
  128. operator=(_Node_handle&&) noexcept = default;
  129. using key_type = _Key;
  130. using mapped_type = typename _Value::second_type;
  131. key_type&
  132. key() const noexcept
  133. {
  134. __glibcxx_assert(!this->empty());
  135. return *_M_pkey;
  136. }
  137. mapped_type&
  138. mapped() const noexcept
  139. {
  140. __glibcxx_assert(!this->empty());
  141. return *_M_pmapped;
  142. }
  143. void
  144. swap(_Node_handle& __nh) noexcept
  145. {
  146. this->_M_swap(__nh);
  147. using std::swap;
  148. swap(_M_pkey, __nh._M_pkey);
  149. swap(_M_pmapped, __nh._M_pmapped);
  150. }
  151. friend void
  152. swap(_Node_handle& __x, _Node_handle& __y)
  153. noexcept(noexcept(__x.swap(__y)))
  154. { __x.swap(__y); }
  155. private:
  156. using _AllocTraits = allocator_traits<_NodeAlloc>;
  157. _Node_handle(typename _AllocTraits::pointer __ptr,
  158. const _NodeAlloc& __alloc)
  159. : _Node_handle_common<_Value, _NodeAlloc>(__ptr, __alloc)
  160. {
  161. if (__ptr)
  162. {
  163. auto& __key = const_cast<_Key&>(__ptr->_M_valptr()->first);
  164. _M_pkey = _S_pointer_to(__key);
  165. _M_pmapped = _S_pointer_to(__ptr->_M_valptr()->second);
  166. }
  167. else
  168. {
  169. _M_pkey = nullptr;
  170. _M_pmapped = nullptr;
  171. }
  172. }
  173. template<typename _Tp>
  174. using __pointer
  175. = __ptr_rebind<typename _AllocTraits::pointer,
  176. remove_reference_t<_Tp>>;
  177. __pointer<_Key> _M_pkey = nullptr;
  178. __pointer<typename _Value::second_type> _M_pmapped = nullptr;
  179. template<typename _Tp>
  180. __pointer<_Tp>
  181. _S_pointer_to(_Tp& __obj)
  182. { return pointer_traits<__pointer<_Tp>>::pointer_to(__obj); }
  183. const key_type&
  184. _M_key() const noexcept { return key(); }
  185. template<typename _Key2, typename _Value2, typename _KeyOfValue,
  186. typename _Compare, typename _ValueAlloc>
  187. friend class _Rb_tree;
  188. template<typename _Key2, typename _Value2, typename _ValueAlloc,
  189. typename _ExtractKey, typename _Equal,
  190. typename _H1, typename _H2, typename _Hash,
  191. typename _RehashPolicy, typename _Traits>
  192. friend class _Hashtable;
  193. };
  194. /// Node handle type for sets.
  195. template<typename _Value, typename _NodeAlloc>
  196. class _Node_handle<_Value, _Value, _NodeAlloc>
  197. : public _Node_handle_common<_Value, _NodeAlloc>
  198. {
  199. public:
  200. constexpr _Node_handle() noexcept = default;
  201. ~_Node_handle() = default;
  202. _Node_handle(_Node_handle&&) noexcept = default;
  203. _Node_handle&
  204. operator=(_Node_handle&&) noexcept = default;
  205. using value_type = _Value;
  206. value_type&
  207. value() const noexcept
  208. {
  209. __glibcxx_assert(!this->empty());
  210. return *this->_M_ptr->_M_valptr();
  211. }
  212. void
  213. swap(_Node_handle& __nh) noexcept
  214. { this->_M_swap(__nh); }
  215. friend void
  216. swap(_Node_handle& __x, _Node_handle& __y)
  217. noexcept(noexcept(__x.swap(__y)))
  218. { __x.swap(__y); }
  219. private:
  220. using _AllocTraits = allocator_traits<_NodeAlloc>;
  221. _Node_handle(typename _AllocTraits::pointer __ptr,
  222. const _NodeAlloc& __alloc)
  223. : _Node_handle_common<_Value, _NodeAlloc>(__ptr, __alloc) { }
  224. const value_type&
  225. _M_key() const noexcept { return value(); }
  226. template<typename _Key, typename _Val, typename _KeyOfValue,
  227. typename _Compare, typename _Alloc>
  228. friend class _Rb_tree;
  229. template<typename _Key2, typename _Value2, typename _ValueAlloc,
  230. typename _ExtractKey, typename _Equal,
  231. typename _H1, typename _H2, typename _Hash,
  232. typename _RehashPolicy, typename _Traits>
  233. friend class _Hashtable;
  234. };
  235. /// Return type of insert(node_handle&&) on unique maps/sets.
  236. template<typename _Iterator, typename _NodeHandle>
  237. struct _Node_insert_return
  238. {
  239. _Iterator position = _Iterator();
  240. bool inserted = false;
  241. _NodeHandle node;
  242. };
  243. _GLIBCXX_END_NAMESPACE_VERSION
  244. } // namespace std
  245. #endif // C++17
  246. #endif