1// -*- C++ -*- 2//===----------------------------------------------------------------------===// 3// 4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5// See https://llvm.org/LICENSE.txt for license information. 6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7// 8//===----------------------------------------------------------------------===// 9 10#ifndef _LIBCPP___NODE_HANDLE 11#define _LIBCPP___NODE_HANDLE 12 13#include <__config> 14#include <__debug> 15#include <memory> 16#include <optional> 17 18#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 19#pragma GCC system_header 20#endif 21 22_LIBCPP_PUSH_MACROS 23#include <__undef_macros> 24 25_LIBCPP_BEGIN_NAMESPACE_STD 26 27#if _LIBCPP_STD_VER > 14 28 29// Specialized in __tree & __hash_table for their _NodeType. 30template <class _NodeType, class _Alloc> 31struct __generic_container_node_destructor; 32 33template <class _NodeType, class _Alloc, 34 template <class, class> class _MapOrSetSpecifics> 35class _LIBCPP_TEMPLATE_VIS __basic_node_handle 36 : public _MapOrSetSpecifics< 37 _NodeType, 38 __basic_node_handle<_NodeType, _Alloc, _MapOrSetSpecifics>> 39{ 40 template <class _Tp, class _Compare, class _Allocator> 41 friend class __tree; 42 template <class _Tp, class _Hash, class _Equal, class _Allocator> 43 friend class __hash_table; 44 friend struct _MapOrSetSpecifics< 45 _NodeType, __basic_node_handle<_NodeType, _Alloc, _MapOrSetSpecifics>>; 46 47 typedef allocator_traits<_Alloc> __alloc_traits; 48 typedef typename __rebind_pointer<typename __alloc_traits::void_pointer, 49 _NodeType>::type 50 __node_pointer_type; 51 52public: 53 typedef _Alloc allocator_type; 54 55private: 56 __node_pointer_type __ptr_ = nullptr; 57 optional<allocator_type> __alloc_; 58 59 _LIBCPP_INLINE_VISIBILITY 60 void __release_ptr() 61 { 62 __ptr_ = nullptr; 63 __alloc_ = _VSTD::nullopt; 64 } 65 66 _LIBCPP_INLINE_VISIBILITY 67 void __destroy_node_pointer() 68 { 69 if (__ptr_ != nullptr) 70 { 71 typedef typename __allocator_traits_rebind< 72 allocator_type, _NodeType>::type __node_alloc_type; 73 __node_alloc_type __alloc(*__alloc_); 74 __generic_container_node_destructor<_NodeType, __node_alloc_type>( 75 __alloc, true)(__ptr_); 76 __ptr_ = nullptr; 77 } 78 } 79 80 _LIBCPP_INLINE_VISIBILITY 81 __basic_node_handle(__node_pointer_type __ptr, 82 allocator_type const& __alloc) 83 : __ptr_(__ptr), __alloc_(__alloc) 84 { 85 } 86 87public: 88 _LIBCPP_INLINE_VISIBILITY 89 __basic_node_handle() = default; 90 91 _LIBCPP_INLINE_VISIBILITY 92 __basic_node_handle(__basic_node_handle&& __other) noexcept 93 : __ptr_(__other.__ptr_), 94 __alloc_(_VSTD::move(__other.__alloc_)) 95 { 96 __other.__ptr_ = nullptr; 97 __other.__alloc_ = _VSTD::nullopt; 98 } 99 100 _LIBCPP_INLINE_VISIBILITY 101 __basic_node_handle& operator=(__basic_node_handle&& __other) 102 { 103 _LIBCPP_ASSERT( 104 __alloc_ == _VSTD::nullopt || 105 __alloc_traits::propagate_on_container_move_assignment::value || 106 __alloc_ == __other.__alloc_, 107 "node_type with incompatible allocator passed to " 108 "node_type::operator=(node_type&&)"); 109 110 __destroy_node_pointer(); 111 __ptr_ = __other.__ptr_; 112 113 if (__alloc_traits::propagate_on_container_move_assignment::value || 114 __alloc_ == _VSTD::nullopt) 115 __alloc_ = _VSTD::move(__other.__alloc_); 116 117 __other.__ptr_ = nullptr; 118 __other.__alloc_ = _VSTD::nullopt; 119 120 return *this; 121 } 122 123 _LIBCPP_INLINE_VISIBILITY 124 allocator_type get_allocator() const { return *__alloc_; } 125 126 _LIBCPP_INLINE_VISIBILITY 127 explicit operator bool() const { return __ptr_ != nullptr; } 128 129 _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY 130 bool empty() const { return __ptr_ == nullptr; } 131 132 _LIBCPP_INLINE_VISIBILITY 133 void swap(__basic_node_handle& __other) noexcept( 134 __alloc_traits::propagate_on_container_swap::value || 135 __alloc_traits::is_always_equal::value) 136 { 137 using _VSTD::swap; 138 swap(__ptr_, __other.__ptr_); 139 if (__alloc_traits::propagate_on_container_swap::value || 140 __alloc_ == _VSTD::nullopt || __other.__alloc_ == _VSTD::nullopt) 141 swap(__alloc_, __other.__alloc_); 142 } 143 144 _LIBCPP_INLINE_VISIBILITY 145 friend void swap(__basic_node_handle& __a, __basic_node_handle& __b) 146 noexcept(noexcept(__a.swap(__b))) { __a.swap(__b); } 147 148 _LIBCPP_INLINE_VISIBILITY 149 ~__basic_node_handle() 150 { 151 __destroy_node_pointer(); 152 } 153}; 154 155template <class _NodeType, class _Derived> 156struct __set_node_handle_specifics 157{ 158 typedef typename _NodeType::__node_value_type value_type; 159 160 _LIBCPP_INLINE_VISIBILITY 161 value_type& value() const 162 { 163 return static_cast<_Derived const*>(this)->__ptr_->__value_; 164 } 165}; 166 167template <class _NodeType, class _Derived> 168struct __map_node_handle_specifics 169{ 170 typedef typename _NodeType::__node_value_type::key_type key_type; 171 typedef typename _NodeType::__node_value_type::mapped_type mapped_type; 172 173 _LIBCPP_INLINE_VISIBILITY 174 key_type& key() const 175 { 176 return static_cast<_Derived const*>(this)-> 177 __ptr_->__value_.__ref().first; 178 } 179 180 _LIBCPP_INLINE_VISIBILITY 181 mapped_type& mapped() const 182 { 183 return static_cast<_Derived const*>(this)-> 184 __ptr_->__value_.__ref().second; 185 } 186}; 187 188template <class _NodeType, class _Alloc> 189using __set_node_handle = 190 __basic_node_handle< _NodeType, _Alloc, __set_node_handle_specifics>; 191 192template <class _NodeType, class _Alloc> 193using __map_node_handle = 194 __basic_node_handle< _NodeType, _Alloc, __map_node_handle_specifics>; 195 196template <class _Iterator, class _NodeType> 197struct _LIBCPP_TEMPLATE_VIS __insert_return_type 198{ 199 _Iterator position; 200 bool inserted; 201 _NodeType node; 202}; 203 204#endif // _LIBCPP_STD_VER > 14 205 206_LIBCPP_END_NAMESPACE_STD 207_LIBCPP_POP_MACROS 208 209#endif // _LIBCPP___NODE_HANDLE 210