211 lines · plain
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-exception7//8//===----------------------------------------------------------------------===//9 10#ifndef _LIBCPP___NODE_HANDLE11#define _LIBCPP___NODE_HANDLE12 13/*14 15template<unspecified>16class node-handle {17public:18 using value_type = see below; // not present for map containers19 using key_type = see below; // not present for set containers20 using mapped_type = see below; // not present for set containers21 using allocator_type = see below;22 23private:24 using container_node_type = unspecified; // exposition only25 using ator_traits = allocator_traits<allocator_type>; // exposition only26 27 typename ator_traits::template28 rebind_traits<container_node_type>::pointer ptr_; // exposition only29 optional<allocator_type> alloc_; // exposition only30 31public:32 // [container.node.cons], constructors, copy, and assignment33 constexpr node-handle() noexcept : ptr_(), alloc_() {}34 node-handle(node-handle&&) noexcept;35 node-handle& operator=(node-handle&&);36 37 // [container.node.dtor], destructor38 ~node-handle();39 40 // [container.node.observers], observers41 value_type& value() const; // not present for map containers42 key_type& key() const; // not present for set containers43 mapped_type& mapped() const; // not present for set containers44 45 allocator_type get_allocator() const;46 explicit operator bool() const noexcept;47 [[nodiscard]] bool empty() const noexcept; // nodiscard since C++2048 49 // [container.node.modifiers], modifiers50 void swap(node-handle&)51 noexcept(ator_traits::propagate_on_container_swap::value ||52 ator_traits::is_always_equal::value);53 54 friend void swap(node-handle& x, node-handle& y) noexcept(noexcept(x.swap(y))) {55 x.swap(y);56 }57};58 59*/60 61#include <__assert>62#include <__config>63#include <__memory/allocator_traits.h>64#include <__memory/pointer_traits.h>65#include <__type_traits/is_specialization.h>66#include <optional>67 68#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)69# pragma GCC system_header70#endif71 72_LIBCPP_PUSH_MACROS73#include <__undef_macros>74 75_LIBCPP_BEGIN_NAMESPACE_STD76 77#if _LIBCPP_STD_VER >= 1778 79// Specialized in __tree & __hash_table for their _NodeType.80template <class _NodeType, class _Alloc>81struct __generic_container_node_destructor;82 83template <class _NodeType, class _Alloc, template <class, class> class _MapOrSetSpecifics>84class __basic_node_handle85 : public _MapOrSetSpecifics< _NodeType, __basic_node_handle<_NodeType, _Alloc, _MapOrSetSpecifics>> {86 template <class _Tp, class _Compare, class _Allocator>87 friend class __tree;88 template <class _Tp, class _Hash, class _Equal, class _Allocator>89 friend class __hash_table;90 friend struct _MapOrSetSpecifics< _NodeType, __basic_node_handle<_NodeType, _Alloc, _MapOrSetSpecifics>>;91 92 typedef allocator_traits<_Alloc> __alloc_traits;93 typedef __rebind_pointer_t<typename __alloc_traits::void_pointer, _NodeType> __node_pointer_type;94 95public:96 typedef _Alloc allocator_type;97 98private:99 __node_pointer_type __ptr_ = nullptr;100 optional<allocator_type> __alloc_;101 102 _LIBCPP_HIDE_FROM_ABI void __release_ptr() {103 __ptr_ = nullptr;104 __alloc_ = std::nullopt;105 }106 107 _LIBCPP_HIDE_FROM_ABI void __destroy_node_pointer() {108 if (__ptr_ != nullptr) {109 typedef typename __allocator_traits_rebind< allocator_type, _NodeType>::type __node_alloc_type;110 __node_alloc_type __alloc(*__alloc_);111 __generic_container_node_destructor<_NodeType, __node_alloc_type>(__alloc, true)(__ptr_);112 __ptr_ = nullptr;113 }114 }115 116 _LIBCPP_HIDE_FROM_ABI __basic_node_handle(__node_pointer_type __ptr, allocator_type const& __alloc)117 : __ptr_(__ptr), __alloc_(__alloc) {}118 119public:120 _LIBCPP_HIDE_FROM_ABI __basic_node_handle() = default;121 122 _LIBCPP_HIDE_FROM_ABI __basic_node_handle(__basic_node_handle&& __other) noexcept123 : __ptr_(__other.__ptr_), __alloc_(std::move(__other.__alloc_)) {124 __other.__ptr_ = nullptr;125 __other.__alloc_ = std::nullopt;126 }127 128 _LIBCPP_HIDE_FROM_ABI __basic_node_handle& operator=(__basic_node_handle&& __other) {129 _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(130 __alloc_ == std::nullopt || __alloc_traits::propagate_on_container_move_assignment::value ||131 __alloc_ == __other.__alloc_,132 "node_type with incompatible allocator passed to "133 "node_type::operator=(node_type&&)");134 135 __destroy_node_pointer();136 __ptr_ = __other.__ptr_;137 138 if (__alloc_traits::propagate_on_container_move_assignment::value || __alloc_ == std::nullopt)139 __alloc_ = std::move(__other.__alloc_);140 141 __other.__ptr_ = nullptr;142 __other.__alloc_ = std::nullopt;143 144 return *this;145 }146 147 _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const { return *__alloc_; }148 149 _LIBCPP_HIDE_FROM_ABI explicit operator bool() const { return __ptr_ != nullptr; }150 151 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool empty() const { return __ptr_ == nullptr; }152 153 _LIBCPP_HIDE_FROM_ABI void swap(__basic_node_handle& __other) noexcept(154 __alloc_traits::propagate_on_container_swap::value || __alloc_traits::is_always_equal::value) {155 using std::swap;156 swap(__ptr_, __other.__ptr_);157 if (__alloc_traits::propagate_on_container_swap::value || __alloc_ == std::nullopt ||158 __other.__alloc_ == std::nullopt)159 swap(__alloc_, __other.__alloc_);160 }161 162 _LIBCPP_HIDE_FROM_ABI friend void163 swap(__basic_node_handle& __a, __basic_node_handle& __b) noexcept(noexcept(__a.swap(__b))) {164 __a.swap(__b);165 }166 167 _LIBCPP_HIDE_FROM_ABI ~__basic_node_handle() { __destroy_node_pointer(); }168};169 170template <class _NodeType, class _Derived>171struct __set_node_handle_specifics {172 typedef typename _NodeType::__node_value_type value_type;173 174 _LIBCPP_HIDE_FROM_ABI value_type& value() const { return static_cast<_Derived const*>(this)->__ptr_->__get_value(); }175};176 177template <class _NodeType, class _Derived>178struct __map_node_handle_specifics {179 using key_type = __remove_const_t<typename _NodeType::__node_value_type::first_type>;180 using mapped_type = typename _NodeType::__node_value_type::second_type;181 182 _LIBCPP_HIDE_FROM_ABI key_type& key() const {183 return const_cast<key_type&>(static_cast<_Derived const*>(this)->__ptr_->__get_value().first);184 }185 186 _LIBCPP_HIDE_FROM_ABI mapped_type& mapped() const {187 return static_cast<_Derived const*>(this)->__ptr_->__get_value().second;188 }189};190 191template <class _NodeType, class _Alloc>192using __set_node_handle _LIBCPP_NODEBUG = __basic_node_handle< _NodeType, _Alloc, __set_node_handle_specifics>;193 194template <class _NodeType, class _Alloc>195using __map_node_handle _LIBCPP_NODEBUG = __basic_node_handle< _NodeType, _Alloc, __map_node_handle_specifics>;196 197template <class _Iterator, class _NodeType>198struct __insert_return_type {199 _Iterator position;200 bool inserted;201 _NodeType node;202};203 204#endif // _LIBCPP_STD_VER >= 17205 206_LIBCPP_END_NAMESPACE_STD207 208_LIBCPP_POP_MACROS209 210#endif // _LIBCPP___NODE_HANDLE211