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