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 71*06c3fb27SDimitry Andric_LIBCPP_PUSH_MACROS 72*06c3fb27SDimitry Andric#include <__undef_macros> 73*06c3fb27SDimitry Andric 740b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD 750b57cec5SDimitry Andric 76*06c3fb27SDimitry 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 820b57cec5SDimitry Andrictemplate <class _NodeType, class _Alloc, 830b57cec5SDimitry Andric template <class, class> class _MapOrSetSpecifics> 840b57cec5SDimitry Andricclass _LIBCPP_TEMPLATE_VIS __basic_node_handle 850b57cec5SDimitry Andric : public _MapOrSetSpecifics< 860b57cec5SDimitry Andric _NodeType, 870b57cec5SDimitry Andric __basic_node_handle<_NodeType, _Alloc, _MapOrSetSpecifics>> 880b57cec5SDimitry Andric{ 890b57cec5SDimitry Andric template <class _Tp, class _Compare, class _Allocator> 900b57cec5SDimitry Andric friend class __tree; 910b57cec5SDimitry Andric template <class _Tp, class _Hash, class _Equal, class _Allocator> 920b57cec5SDimitry Andric friend class __hash_table; 930b57cec5SDimitry Andric friend struct _MapOrSetSpecifics< 940b57cec5SDimitry Andric _NodeType, __basic_node_handle<_NodeType, _Alloc, _MapOrSetSpecifics>>; 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric typedef allocator_traits<_Alloc> __alloc_traits; 97bdd1243dSDimitry Andric typedef __rebind_pointer_t<typename __alloc_traits::void_pointer, 98bdd1243dSDimitry Andric _NodeType> 990b57cec5SDimitry Andric __node_pointer_type; 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andricpublic: 1020b57cec5SDimitry Andric typedef _Alloc allocator_type; 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andricprivate: 1050b57cec5SDimitry Andric __node_pointer_type __ptr_ = nullptr; 1060b57cec5SDimitry Andric optional<allocator_type> __alloc_; 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 1090b57cec5SDimitry Andric void __release_ptr() 1100b57cec5SDimitry Andric { 1110b57cec5SDimitry Andric __ptr_ = nullptr; 1120b57cec5SDimitry Andric __alloc_ = _VSTD::nullopt; 1130b57cec5SDimitry Andric } 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 1160b57cec5SDimitry Andric void __destroy_node_pointer() 1170b57cec5SDimitry Andric { 1180b57cec5SDimitry Andric if (__ptr_ != nullptr) 1190b57cec5SDimitry Andric { 1200b57cec5SDimitry Andric typedef typename __allocator_traits_rebind< 1210b57cec5SDimitry Andric allocator_type, _NodeType>::type __node_alloc_type; 1220b57cec5SDimitry Andric __node_alloc_type __alloc(*__alloc_); 1230b57cec5SDimitry Andric __generic_container_node_destructor<_NodeType, __node_alloc_type>( 1240b57cec5SDimitry Andric __alloc, true)(__ptr_); 1250b57cec5SDimitry Andric __ptr_ = nullptr; 1260b57cec5SDimitry Andric } 1270b57cec5SDimitry Andric } 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 1300b57cec5SDimitry Andric __basic_node_handle(__node_pointer_type __ptr, 1310b57cec5SDimitry Andric allocator_type const& __alloc) 1320b57cec5SDimitry Andric : __ptr_(__ptr), __alloc_(__alloc) 1330b57cec5SDimitry Andric { 1340b57cec5SDimitry Andric } 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andricpublic: 1370b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 1380b57cec5SDimitry Andric __basic_node_handle() = default; 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 1410b57cec5SDimitry Andric __basic_node_handle(__basic_node_handle&& __other) noexcept 1420b57cec5SDimitry Andric : __ptr_(__other.__ptr_), 1430b57cec5SDimitry Andric __alloc_(_VSTD::move(__other.__alloc_)) 1440b57cec5SDimitry Andric { 1450b57cec5SDimitry Andric __other.__ptr_ = nullptr; 1460b57cec5SDimitry Andric __other.__alloc_ = _VSTD::nullopt; 1470b57cec5SDimitry Andric } 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 1500b57cec5SDimitry Andric __basic_node_handle& operator=(__basic_node_handle&& __other) 1510b57cec5SDimitry Andric { 152*06c3fb27SDimitry Andric _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR( 1530b57cec5SDimitry Andric __alloc_ == _VSTD::nullopt || 1540b57cec5SDimitry Andric __alloc_traits::propagate_on_container_move_assignment::value || 1550b57cec5SDimitry Andric __alloc_ == __other.__alloc_, 1560b57cec5SDimitry Andric "node_type with incompatible allocator passed to " 1570b57cec5SDimitry Andric "node_type::operator=(node_type&&)"); 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric __destroy_node_pointer(); 1600b57cec5SDimitry Andric __ptr_ = __other.__ptr_; 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric if (__alloc_traits::propagate_on_container_move_assignment::value || 1630b57cec5SDimitry Andric __alloc_ == _VSTD::nullopt) 1640b57cec5SDimitry Andric __alloc_ = _VSTD::move(__other.__alloc_); 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric __other.__ptr_ = nullptr; 1670b57cec5SDimitry Andric __other.__alloc_ = _VSTD::nullopt; 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric return *this; 1700b57cec5SDimitry Andric } 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 1730b57cec5SDimitry Andric allocator_type get_allocator() const { return *__alloc_; } 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 1760b57cec5SDimitry Andric explicit operator bool() const { return __ptr_ != nullptr; } 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY 1790b57cec5SDimitry Andric bool empty() const { return __ptr_ == nullptr; } 1800b57cec5SDimitry Andric 1810b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 1820b57cec5SDimitry Andric void swap(__basic_node_handle& __other) noexcept( 1830b57cec5SDimitry Andric __alloc_traits::propagate_on_container_swap::value || 1840b57cec5SDimitry Andric __alloc_traits::is_always_equal::value) 1850b57cec5SDimitry Andric { 1860b57cec5SDimitry Andric using _VSTD::swap; 1870b57cec5SDimitry Andric swap(__ptr_, __other.__ptr_); 1880b57cec5SDimitry Andric if (__alloc_traits::propagate_on_container_swap::value || 1890b57cec5SDimitry Andric __alloc_ == _VSTD::nullopt || __other.__alloc_ == _VSTD::nullopt) 1900b57cec5SDimitry Andric swap(__alloc_, __other.__alloc_); 1910b57cec5SDimitry Andric } 1920b57cec5SDimitry Andric 1930b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 1940b57cec5SDimitry Andric friend void swap(__basic_node_handle& __a, __basic_node_handle& __b) 1950b57cec5SDimitry Andric noexcept(noexcept(__a.swap(__b))) { __a.swap(__b); } 1960b57cec5SDimitry Andric 1970b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 1980b57cec5SDimitry Andric ~__basic_node_handle() 1990b57cec5SDimitry Andric { 2000b57cec5SDimitry Andric __destroy_node_pointer(); 2010b57cec5SDimitry Andric } 2020b57cec5SDimitry Andric}; 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andrictemplate <class _NodeType, class _Derived> 2050b57cec5SDimitry Andricstruct __set_node_handle_specifics 2060b57cec5SDimitry Andric{ 2070b57cec5SDimitry Andric typedef typename _NodeType::__node_value_type value_type; 2080b57cec5SDimitry Andric 2090b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2100b57cec5SDimitry Andric value_type& value() const 2110b57cec5SDimitry Andric { 2120b57cec5SDimitry Andric return static_cast<_Derived const*>(this)->__ptr_->__value_; 2130b57cec5SDimitry Andric } 2140b57cec5SDimitry Andric}; 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andrictemplate <class _NodeType, class _Derived> 2170b57cec5SDimitry Andricstruct __map_node_handle_specifics 2180b57cec5SDimitry Andric{ 2190b57cec5SDimitry Andric typedef typename _NodeType::__node_value_type::key_type key_type; 2200b57cec5SDimitry Andric typedef typename _NodeType::__node_value_type::mapped_type mapped_type; 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2230b57cec5SDimitry Andric key_type& key() const 2240b57cec5SDimitry Andric { 2250b57cec5SDimitry Andric return static_cast<_Derived const*>(this)-> 2260b57cec5SDimitry Andric __ptr_->__value_.__ref().first; 2270b57cec5SDimitry Andric } 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2300b57cec5SDimitry Andric mapped_type& mapped() const 2310b57cec5SDimitry Andric { 2320b57cec5SDimitry Andric return static_cast<_Derived const*>(this)-> 2330b57cec5SDimitry Andric __ptr_->__value_.__ref().second; 2340b57cec5SDimitry Andric } 2350b57cec5SDimitry Andric}; 2360b57cec5SDimitry Andric 2370b57cec5SDimitry Andrictemplate <class _NodeType, class _Alloc> 2380b57cec5SDimitry Andricusing __set_node_handle = 2390b57cec5SDimitry Andric __basic_node_handle< _NodeType, _Alloc, __set_node_handle_specifics>; 2400b57cec5SDimitry Andric 2410b57cec5SDimitry Andrictemplate <class _NodeType, class _Alloc> 2420b57cec5SDimitry Andricusing __map_node_handle = 2430b57cec5SDimitry Andric __basic_node_handle< _NodeType, _Alloc, __map_node_handle_specifics>; 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andrictemplate <class _Iterator, class _NodeType> 2460b57cec5SDimitry Andricstruct _LIBCPP_TEMPLATE_VIS __insert_return_type 2470b57cec5SDimitry Andric{ 2480b57cec5SDimitry Andric _Iterator position; 2490b57cec5SDimitry Andric bool inserted; 2500b57cec5SDimitry Andric _NodeType node; 2510b57cec5SDimitry Andric}; 2520b57cec5SDimitry Andric 253*06c3fb27SDimitry Andric#endif // _LIBCPP_STD_VER >= 17 2540b57cec5SDimitry Andric 2550b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_STD 2560b57cec5SDimitry Andric 257*06c3fb27SDimitry Andric_LIBCPP_POP_MACROS 258*06c3fb27SDimitry Andric 259fe6060f1SDimitry Andric#endif // _LIBCPP___NODE_HANDLE 260