10b57cec5SDimitry Andric// -*- C++ -*- 20b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 30b57cec5SDimitry Andric// 40b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 50b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information. 60b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 70b57cec5SDimitry Andric// 80b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 90b57cec5SDimitry Andric 100b57cec5SDimitry Andric#ifndef _LIBCPP___NODE_HANDLE 110b57cec5SDimitry Andric#define _LIBCPP___NODE_HANDLE 120b57cec5SDimitry Andric 13349cc55cSDimitry Andric/* 14349cc55cSDimitry Andric 15349cc55cSDimitry Andrictemplate<unspecified> 16349cc55cSDimitry Andricclass node-handle { 17349cc55cSDimitry Andricpublic: 18349cc55cSDimitry Andric using value_type = see below; // not present for map containers 19349cc55cSDimitry Andric using key_type = see below; // not present for set containers 20349cc55cSDimitry Andric using mapped_type = see below; // not present for set containers 21349cc55cSDimitry Andric using allocator_type = see below; 22349cc55cSDimitry Andric 23349cc55cSDimitry Andricprivate: 24349cc55cSDimitry Andric using container_node_type = unspecified; // exposition only 25349cc55cSDimitry Andric using ator_traits = allocator_traits<allocator_type>; // exposition only 26349cc55cSDimitry Andric 27349cc55cSDimitry Andric typename ator_traits::template 28349cc55cSDimitry Andric rebind_traits<container_node_type>::pointer ptr_; // exposition only 29349cc55cSDimitry Andric optional<allocator_type> alloc_; // exposition only 30349cc55cSDimitry Andric 31349cc55cSDimitry Andricpublic: 32349cc55cSDimitry Andric // [container.node.cons], constructors, copy, and assignment 33349cc55cSDimitry Andric constexpr node-handle() noexcept : ptr_(), alloc_() {} 34349cc55cSDimitry Andric node-handle(node-handle&&) noexcept; 35349cc55cSDimitry Andric node-handle& operator=(node-handle&&); 36349cc55cSDimitry Andric 37349cc55cSDimitry Andric // [container.node.dtor], destructor 38349cc55cSDimitry Andric ~node-handle(); 39349cc55cSDimitry Andric 40349cc55cSDimitry Andric // [container.node.observers], observers 41349cc55cSDimitry Andric value_type& value() const; // not present for map containers 42349cc55cSDimitry Andric key_type& key() const; // not present for set containers 43349cc55cSDimitry Andric mapped_type& mapped() const; // not present for set containers 44349cc55cSDimitry Andric 45349cc55cSDimitry Andric allocator_type get_allocator() const; 46349cc55cSDimitry Andric explicit operator bool() const noexcept; 47349cc55cSDimitry Andric [[nodiscard]] bool empty() const noexcept; // nodiscard since C++20 48349cc55cSDimitry Andric 49349cc55cSDimitry Andric // [container.node.modifiers], modifiers 50349cc55cSDimitry Andric void swap(node-handle&) 51349cc55cSDimitry Andric noexcept(ator_traits::propagate_on_container_swap::value || 52349cc55cSDimitry Andric ator_traits::is_always_equal::value); 53349cc55cSDimitry Andric 54349cc55cSDimitry Andric friend void swap(node-handle& x, node-handle& y) noexcept(noexcept(x.swap(y))) { 55349cc55cSDimitry Andric x.swap(y); 56349cc55cSDimitry Andric } 57349cc55cSDimitry Andric}; 58349cc55cSDimitry Andric 59349cc55cSDimitry Andric*/ 60349cc55cSDimitry Andric 6181ad6265SDimitry Andric#include <__assert> 620b57cec5SDimitry Andric#include <__config> 63bdd1243dSDimitry Andric#include <__memory/allocator_traits.h> 64bdd1243dSDimitry Andric#include <__memory/pointer_traits.h> 650b57cec5SDimitry Andric#include <optional> 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 680b57cec5SDimitry Andric# pragma GCC system_header 690b57cec5SDimitry Andric#endif 700b57cec5SDimitry Andric 7106c3fb27SDimitry Andric_LIBCPP_PUSH_MACROS 7206c3fb27SDimitry Andric#include <__undef_macros> 7306c3fb27SDimitry Andric 740b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD 750b57cec5SDimitry Andric 7606c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 17 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric// Specialized in __tree & __hash_table for their _NodeType. 790b57cec5SDimitry Andrictemplate <class _NodeType, class _Alloc> 800b57cec5SDimitry Andricstruct __generic_container_node_destructor; 810b57cec5SDimitry Andric 82cb14a3feSDimitry Andrictemplate <class _NodeType, class _Alloc, template <class, class> class _MapOrSetSpecifics> 830b57cec5SDimitry Andricclass _LIBCPP_TEMPLATE_VIS __basic_node_handle 84cb14a3feSDimitry Andric : public _MapOrSetSpecifics< _NodeType, __basic_node_handle<_NodeType, _Alloc, _MapOrSetSpecifics>> { 850b57cec5SDimitry Andric template <class _Tp, class _Compare, class _Allocator> 860b57cec5SDimitry Andric friend class __tree; 870b57cec5SDimitry Andric template <class _Tp, class _Hash, class _Equal, class _Allocator> 880b57cec5SDimitry Andric friend class __hash_table; 89cb14a3feSDimitry Andric friend struct _MapOrSetSpecifics< _NodeType, __basic_node_handle<_NodeType, _Alloc, _MapOrSetSpecifics>>; 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric typedef allocator_traits<_Alloc> __alloc_traits; 92cb14a3feSDimitry Andric typedef __rebind_pointer_t<typename __alloc_traits::void_pointer, _NodeType> __node_pointer_type; 930b57cec5SDimitry Andric 940b57cec5SDimitry Andricpublic: 950b57cec5SDimitry Andric typedef _Alloc allocator_type; 960b57cec5SDimitry Andric 970b57cec5SDimitry Andricprivate: 980b57cec5SDimitry Andric __node_pointer_type __ptr_ = nullptr; 990b57cec5SDimitry Andric optional<allocator_type> __alloc_; 1000b57cec5SDimitry Andric 101cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __release_ptr() { 1020b57cec5SDimitry Andric __ptr_ = nullptr; 1035f757f3fSDimitry Andric __alloc_ = std::nullopt; 1040b57cec5SDimitry Andric } 1050b57cec5SDimitry Andric 106cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __destroy_node_pointer() { 107cb14a3feSDimitry Andric if (__ptr_ != nullptr) { 108cb14a3feSDimitry Andric typedef typename __allocator_traits_rebind< allocator_type, _NodeType>::type __node_alloc_type; 1090b57cec5SDimitry Andric __node_alloc_type __alloc(*__alloc_); 110cb14a3feSDimitry Andric __generic_container_node_destructor<_NodeType, __node_alloc_type>(__alloc, true)(__ptr_); 1110b57cec5SDimitry Andric __ptr_ = nullptr; 1120b57cec5SDimitry Andric } 1130b57cec5SDimitry Andric } 1140b57cec5SDimitry Andric 115cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __basic_node_handle(__node_pointer_type __ptr, allocator_type const& __alloc) 116cb14a3feSDimitry Andric : __ptr_(__ptr), __alloc_(__alloc) {} 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andricpublic: 119cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __basic_node_handle() = default; 1200b57cec5SDimitry Andric 121cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __basic_node_handle(__basic_node_handle&& __other) noexcept 122cb14a3feSDimitry Andric : __ptr_(__other.__ptr_), __alloc_(std::move(__other.__alloc_)) { 1230b57cec5SDimitry Andric __other.__ptr_ = nullptr; 1245f757f3fSDimitry Andric __other.__alloc_ = std::nullopt; 1250b57cec5SDimitry Andric } 1260b57cec5SDimitry Andric 127cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __basic_node_handle& operator=(__basic_node_handle&& __other) { 12806c3fb27SDimitry Andric _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR( 129cb14a3feSDimitry Andric __alloc_ == std::nullopt || __alloc_traits::propagate_on_container_move_assignment::value || 1300b57cec5SDimitry Andric __alloc_ == __other.__alloc_, 1310b57cec5SDimitry Andric "node_type with incompatible allocator passed to " 1320b57cec5SDimitry Andric "node_type::operator=(node_type&&)"); 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric __destroy_node_pointer(); 1350b57cec5SDimitry Andric __ptr_ = __other.__ptr_; 1360b57cec5SDimitry Andric 137cb14a3feSDimitry Andric if (__alloc_traits::propagate_on_container_move_assignment::value || __alloc_ == std::nullopt) 1385f757f3fSDimitry Andric __alloc_ = std::move(__other.__alloc_); 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric __other.__ptr_ = nullptr; 1415f757f3fSDimitry Andric __other.__alloc_ = std::nullopt; 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric return *this; 1440b57cec5SDimitry Andric } 1450b57cec5SDimitry Andric 146cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const { return *__alloc_; } 1470b57cec5SDimitry Andric 148cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit operator bool() const { return __ptr_ != nullptr; } 1490b57cec5SDimitry Andric 150*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool empty() const { return __ptr_ == nullptr; } 1510b57cec5SDimitry Andric 152cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void swap(__basic_node_handle& __other) noexcept( 153cb14a3feSDimitry Andric __alloc_traits::propagate_on_container_swap::value || __alloc_traits::is_always_equal::value) { 1545f757f3fSDimitry Andric using std::swap; 1550b57cec5SDimitry Andric swap(__ptr_, __other.__ptr_); 156cb14a3feSDimitry Andric if (__alloc_traits::propagate_on_container_swap::value || __alloc_ == std::nullopt || 157cb14a3feSDimitry Andric __other.__alloc_ == std::nullopt) 1580b57cec5SDimitry Andric swap(__alloc_, __other.__alloc_); 1590b57cec5SDimitry Andric } 1600b57cec5SDimitry Andric 161cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend void 162cb14a3feSDimitry Andric swap(__basic_node_handle& __a, __basic_node_handle& __b) noexcept(noexcept(__a.swap(__b))) { 163cb14a3feSDimitry Andric __a.swap(__b); 1640b57cec5SDimitry Andric } 165cb14a3feSDimitry Andric 166cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI ~__basic_node_handle() { __destroy_node_pointer(); } 1670b57cec5SDimitry Andric}; 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andrictemplate <class _NodeType, class _Derived> 170cb14a3feSDimitry Andricstruct __set_node_handle_specifics { 1710b57cec5SDimitry Andric typedef typename _NodeType::__node_value_type value_type; 1720b57cec5SDimitry Andric 173cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI value_type& value() const { return static_cast<_Derived const*>(this)->__ptr_->__get_value(); } 1740b57cec5SDimitry Andric}; 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andrictemplate <class _NodeType, class _Derived> 177cb14a3feSDimitry Andricstruct __map_node_handle_specifics { 1780b57cec5SDimitry Andric typedef typename _NodeType::__node_value_type::key_type key_type; 1790b57cec5SDimitry Andric typedef typename _NodeType::__node_value_type::mapped_type mapped_type; 1800b57cec5SDimitry Andric 181cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI key_type& key() const { 182cb14a3feSDimitry Andric return static_cast<_Derived const*>(this)->__ptr_->__get_value().__ref().first; 1830b57cec5SDimitry Andric } 1840b57cec5SDimitry Andric 185cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI mapped_type& mapped() const { 186cb14a3feSDimitry Andric return static_cast<_Derived const*>(this)->__ptr_->__get_value().__ref().second; 1870b57cec5SDimitry Andric } 1880b57cec5SDimitry Andric}; 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andrictemplate <class _NodeType, class _Alloc> 191cb14a3feSDimitry Andricusing __set_node_handle = __basic_node_handle< _NodeType, _Alloc, __set_node_handle_specifics>; 1920b57cec5SDimitry Andric 1930b57cec5SDimitry Andrictemplate <class _NodeType, class _Alloc> 194cb14a3feSDimitry Andricusing __map_node_handle = __basic_node_handle< _NodeType, _Alloc, __map_node_handle_specifics>; 1950b57cec5SDimitry Andric 1960b57cec5SDimitry Andrictemplate <class _Iterator, class _NodeType> 197cb14a3feSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS __insert_return_type { 1980b57cec5SDimitry Andric _Iterator position; 1990b57cec5SDimitry Andric bool inserted; 2000b57cec5SDimitry Andric _NodeType node; 2010b57cec5SDimitry Andric}; 2020b57cec5SDimitry Andric 20306c3fb27SDimitry Andric#endif // _LIBCPP_STD_VER >= 17 2040b57cec5SDimitry Andric 2050b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_STD 2060b57cec5SDimitry Andric 20706c3fb27SDimitry Andric_LIBCPP_POP_MACROS 20806c3fb27SDimitry Andric 209fe6060f1SDimitry Andric#endif // _LIBCPP___NODE_HANDLE 210