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