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