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