1b0386a51SErik Pilkington// -*- C++ -*-
2b0386a51SErik Pilkington//===----------------------------------------------------------------------===//
3b0386a51SErik Pilkington//
457b08b09SChandler Carruth// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
557b08b09SChandler Carruth// See https://llvm.org/LICENSE.txt for license information.
657b08b09SChandler Carruth// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7b0386a51SErik Pilkington//
8b0386a51SErik Pilkington//===----------------------------------------------------------------------===//
9b0386a51SErik Pilkington
10b0386a51SErik Pilkington#ifndef _LIBCPP___NODE_HANDLE
11b0386a51SErik Pilkington#define _LIBCPP___NODE_HANDLE
12b0386a51SErik Pilkington
1308d56432SLouis Dionne/*
1408d56432SLouis Dionne
1508d56432SLouis Dionnetemplate<unspecified>
1608d56432SLouis Dionneclass node-handle {
1708d56432SLouis Dionnepublic:
1808d56432SLouis Dionne  using value_type     = see below;     // not present for map containers
1908d56432SLouis Dionne  using key_type       = see below;     // not present for set containers
2008d56432SLouis Dionne  using mapped_type    = see below;     // not present for set containers
2108d56432SLouis Dionne  using allocator_type = see below;
2208d56432SLouis Dionne
2308d56432SLouis Dionneprivate:
2408d56432SLouis Dionne  using container_node_type = unspecified;                  // exposition only
2508d56432SLouis Dionne  using ator_traits = allocator_traits<allocator_type>;     // exposition only
2608d56432SLouis Dionne
2708d56432SLouis Dionne  typename ator_traits::template
2808d56432SLouis Dionne    rebind_traits<container_node_type>::pointer ptr_;       // exposition only
2908d56432SLouis Dionne  optional<allocator_type> alloc_;                          // exposition only
3008d56432SLouis Dionne
3108d56432SLouis Dionnepublic:
3208d56432SLouis Dionne  // [container.node.cons], constructors, copy, and assignment
3308d56432SLouis Dionne  constexpr node-handle() noexcept : ptr_(), alloc_() {}
3408d56432SLouis Dionne  node-handle(node-handle&&) noexcept;
3508d56432SLouis Dionne  node-handle& operator=(node-handle&&);
3608d56432SLouis Dionne
3708d56432SLouis Dionne  // [container.node.dtor], destructor
3808d56432SLouis Dionne  ~node-handle();
3908d56432SLouis Dionne
4008d56432SLouis Dionne  // [container.node.observers], observers
4108d56432SLouis Dionne  value_type& value() const;            // not present for map containers
4208d56432SLouis Dionne  key_type& key() const;                // not present for set containers
4308d56432SLouis Dionne  mapped_type& mapped() const;          // not present for set containers
4408d56432SLouis Dionne
4508d56432SLouis Dionne  allocator_type get_allocator() const;
4608d56432SLouis Dionne  explicit operator bool() const noexcept;
4708d56432SLouis Dionne  [[nodiscard]] bool empty() const noexcept; // nodiscard since C++20
4808d56432SLouis Dionne
4908d56432SLouis Dionne  // [container.node.modifiers], modifiers
5008d56432SLouis Dionne  void swap(node-handle&)
5108d56432SLouis Dionne    noexcept(ator_traits::propagate_on_container_swap::value ||
5208d56432SLouis Dionne             ator_traits::is_always_equal::value);
5308d56432SLouis Dionne
5408d56432SLouis Dionne  friend void swap(node-handle& x, node-handle& y) noexcept(noexcept(x.swap(y))) {
5508d56432SLouis Dionne    x.swap(y);
5608d56432SLouis Dionne  }
5708d56432SLouis Dionne};
5808d56432SLouis Dionne
5908d56432SLouis Dionne*/
6008d56432SLouis Dionne
61*f87aa19bSLouis Dionne#include <__assert>
62b0386a51SErik Pilkington#include <__config>
63b0386a51SErik Pilkington#include <memory>
64b0386a51SErik Pilkington#include <optional>
65b0386a51SErik Pilkington
66b0386a51SErik Pilkington#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
67b0386a51SErik Pilkington#  pragma GCC system_header
68b0386a51SErik Pilkington#endif
69b0386a51SErik Pilkington
70b0386a51SErik Pilkington_LIBCPP_BEGIN_NAMESPACE_STD
71b0386a51SErik Pilkington
72b0386a51SErik Pilkington#if _LIBCPP_STD_VER > 14
73b0386a51SErik Pilkington
74b0386a51SErik Pilkington// Specialized in __tree & __hash_table for their _NodeType.
75b0386a51SErik Pilkingtontemplate <class _NodeType, class _Alloc>
76b0386a51SErik Pilkingtonstruct __generic_container_node_destructor;
77b0386a51SErik Pilkington
78b0386a51SErik Pilkingtontemplate <class _NodeType, class _Alloc,
79b0386a51SErik Pilkington          template <class, class> class _MapOrSetSpecifics>
80b0386a51SErik Pilkingtonclass _LIBCPP_TEMPLATE_VIS __basic_node_handle
81b0386a51SErik Pilkington    : public _MapOrSetSpecifics<
82b0386a51SErik Pilkington          _NodeType,
83b0386a51SErik Pilkington          __basic_node_handle<_NodeType, _Alloc, _MapOrSetSpecifics>>
84b0386a51SErik Pilkington{
85b0386a51SErik Pilkington    template <class _Tp, class _Compare, class _Allocator>
86b0386a51SErik Pilkington        friend class __tree;
87b0386a51SErik Pilkington    template <class _Tp, class _Hash, class _Equal, class _Allocator>
88b0386a51SErik Pilkington        friend class __hash_table;
89b0386a51SErik Pilkington    friend struct _MapOrSetSpecifics<
90b0386a51SErik Pilkington        _NodeType, __basic_node_handle<_NodeType, _Alloc, _MapOrSetSpecifics>>;
91b0386a51SErik Pilkington
92b0386a51SErik Pilkington    typedef allocator_traits<_Alloc> __alloc_traits;
93b0386a51SErik Pilkington    typedef typename __rebind_pointer<typename __alloc_traits::void_pointer,
94b0386a51SErik Pilkington                                      _NodeType>::type
95b0386a51SErik Pilkington        __node_pointer_type;
96b0386a51SErik Pilkington
97b0386a51SErik Pilkingtonpublic:
98b0386a51SErik Pilkington    typedef _Alloc allocator_type;
99b0386a51SErik Pilkington
100b0386a51SErik Pilkingtonprivate:
101b0386a51SErik Pilkington    __node_pointer_type __ptr_ = nullptr;
102b0386a51SErik Pilkington    optional<allocator_type> __alloc_;
103b0386a51SErik Pilkington
104b0386a51SErik Pilkington    _LIBCPP_INLINE_VISIBILITY
1056886f1e3SEric Fiselier    void __release_ptr()
106b0386a51SErik Pilkington    {
107b0386a51SErik Pilkington        __ptr_ = nullptr;
108b0386a51SErik Pilkington        __alloc_ = _VSTD::nullopt;
109b0386a51SErik Pilkington    }
110b0386a51SErik Pilkington
111b0386a51SErik Pilkington    _LIBCPP_INLINE_VISIBILITY
112b0386a51SErik Pilkington    void __destroy_node_pointer()
113b0386a51SErik Pilkington    {
114b0386a51SErik Pilkington        if (__ptr_ != nullptr)
115b0386a51SErik Pilkington        {
116b0386a51SErik Pilkington            typedef typename __allocator_traits_rebind<
117b0386a51SErik Pilkington                allocator_type, _NodeType>::type __node_alloc_type;
118b0386a51SErik Pilkington            __node_alloc_type __alloc(*__alloc_);
119b0386a51SErik Pilkington            __generic_container_node_destructor<_NodeType, __node_alloc_type>(
120b0386a51SErik Pilkington                __alloc, true)(__ptr_);
121b0386a51SErik Pilkington            __ptr_ = nullptr;
122b0386a51SErik Pilkington        }
123b0386a51SErik Pilkington    }
124b0386a51SErik Pilkington
125b0386a51SErik Pilkington    _LIBCPP_INLINE_VISIBILITY
126b0386a51SErik Pilkington    __basic_node_handle(__node_pointer_type __ptr,
127b0386a51SErik Pilkington                        allocator_type const& __alloc)
128b0386a51SErik Pilkington            : __ptr_(__ptr), __alloc_(__alloc)
129b0386a51SErik Pilkington    {
130b0386a51SErik Pilkington    }
131b0386a51SErik Pilkington
132b0386a51SErik Pilkingtonpublic:
133b0386a51SErik Pilkington    _LIBCPP_INLINE_VISIBILITY
134b0386a51SErik Pilkington    __basic_node_handle() = default;
135b0386a51SErik Pilkington
136b0386a51SErik Pilkington    _LIBCPP_INLINE_VISIBILITY
137b0386a51SErik Pilkington    __basic_node_handle(__basic_node_handle&& __other) noexcept
138b0386a51SErik Pilkington            : __ptr_(__other.__ptr_),
139b0386a51SErik Pilkington              __alloc_(_VSTD::move(__other.__alloc_))
140b0386a51SErik Pilkington    {
141b0386a51SErik Pilkington        __other.__ptr_ = nullptr;
142b0386a51SErik Pilkington        __other.__alloc_ = _VSTD::nullopt;
143b0386a51SErik Pilkington    }
144b0386a51SErik Pilkington
145b0386a51SErik Pilkington    _LIBCPP_INLINE_VISIBILITY
146b0386a51SErik Pilkington    __basic_node_handle& operator=(__basic_node_handle&& __other)
147b0386a51SErik Pilkington    {
148b0386a51SErik Pilkington        _LIBCPP_ASSERT(
149b0386a51SErik Pilkington            __alloc_ == _VSTD::nullopt ||
150b0386a51SErik Pilkington            __alloc_traits::propagate_on_container_move_assignment::value ||
151b0386a51SErik Pilkington            __alloc_ == __other.__alloc_,
152b0386a51SErik Pilkington            "node_type with incompatible allocator passed to "
153b0386a51SErik Pilkington            "node_type::operator=(node_type&&)");
154b0386a51SErik Pilkington
155b0386a51SErik Pilkington        __destroy_node_pointer();
156b0386a51SErik Pilkington        __ptr_ = __other.__ptr_;
157b0386a51SErik Pilkington
158b0386a51SErik Pilkington        if (__alloc_traits::propagate_on_container_move_assignment::value ||
159b0386a51SErik Pilkington            __alloc_ == _VSTD::nullopt)
160b0386a51SErik Pilkington            __alloc_ = _VSTD::move(__other.__alloc_);
161b0386a51SErik Pilkington
162b0386a51SErik Pilkington        __other.__ptr_ = nullptr;
163b0386a51SErik Pilkington        __other.__alloc_ = _VSTD::nullopt;
164b0386a51SErik Pilkington
165b0386a51SErik Pilkington        return *this;
166b0386a51SErik Pilkington    }
167b0386a51SErik Pilkington
168b0386a51SErik Pilkington    _LIBCPP_INLINE_VISIBILITY
169b0386a51SErik Pilkington    allocator_type get_allocator() const { return *__alloc_; }
170b0386a51SErik Pilkington
171b0386a51SErik Pilkington    _LIBCPP_INLINE_VISIBILITY
172b0386a51SErik Pilkington    explicit operator bool() const { return __ptr_ != nullptr; }
173b0386a51SErik Pilkington
174b0386a51SErik Pilkington    _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
175b0386a51SErik Pilkington    bool empty() const { return __ptr_ == nullptr; }
176b0386a51SErik Pilkington
177b0386a51SErik Pilkington    _LIBCPP_INLINE_VISIBILITY
178b0386a51SErik Pilkington    void swap(__basic_node_handle& __other) noexcept(
179b0386a51SErik Pilkington        __alloc_traits::propagate_on_container_swap::value ||
180b0386a51SErik Pilkington        __alloc_traits::is_always_equal::value)
181b0386a51SErik Pilkington    {
182b0386a51SErik Pilkington        using _VSTD::swap;
183b0386a51SErik Pilkington        swap(__ptr_, __other.__ptr_);
184b0386a51SErik Pilkington        if (__alloc_traits::propagate_on_container_swap::value ||
185b0386a51SErik Pilkington            __alloc_ == _VSTD::nullopt || __other.__alloc_ == _VSTD::nullopt)
186b0386a51SErik Pilkington            swap(__alloc_, __other.__alloc_);
187b0386a51SErik Pilkington    }
188b0386a51SErik Pilkington
189b0386a51SErik Pilkington    _LIBCPP_INLINE_VISIBILITY
190b0386a51SErik Pilkington    friend void swap(__basic_node_handle& __a, __basic_node_handle& __b)
191b0386a51SErik Pilkington        noexcept(noexcept(__a.swap(__b))) { __a.swap(__b); }
192b0386a51SErik Pilkington
193b0386a51SErik Pilkington    _LIBCPP_INLINE_VISIBILITY
194b0386a51SErik Pilkington    ~__basic_node_handle()
195b0386a51SErik Pilkington    {
196b0386a51SErik Pilkington        __destroy_node_pointer();
197b0386a51SErik Pilkington    }
198b0386a51SErik Pilkington};
199b0386a51SErik Pilkington
200b0386a51SErik Pilkingtontemplate <class _NodeType, class _Derived>
201b0386a51SErik Pilkingtonstruct __set_node_handle_specifics
202b0386a51SErik Pilkington{
203b0386a51SErik Pilkington    typedef typename _NodeType::__node_value_type value_type;
204b0386a51SErik Pilkington
205b0386a51SErik Pilkington    _LIBCPP_INLINE_VISIBILITY
206b0386a51SErik Pilkington    value_type& value() const
207b0386a51SErik Pilkington    {
208b0386a51SErik Pilkington        return static_cast<_Derived const*>(this)->__ptr_->__value_;
209b0386a51SErik Pilkington    }
210b0386a51SErik Pilkington};
211b0386a51SErik Pilkington
212b0386a51SErik Pilkingtontemplate <class _NodeType, class _Derived>
213b0386a51SErik Pilkingtonstruct __map_node_handle_specifics
214b0386a51SErik Pilkington{
215b0386a51SErik Pilkington    typedef typename _NodeType::__node_value_type::key_type key_type;
216b0386a51SErik Pilkington    typedef typename _NodeType::__node_value_type::mapped_type mapped_type;
217b0386a51SErik Pilkington
218b0386a51SErik Pilkington    _LIBCPP_INLINE_VISIBILITY
219b0386a51SErik Pilkington    key_type& key() const
220b0386a51SErik Pilkington    {
221b0386a51SErik Pilkington        return static_cast<_Derived const*>(this)->
222b0386a51SErik Pilkington            __ptr_->__value_.__ref().first;
223b0386a51SErik Pilkington    }
224b0386a51SErik Pilkington
225b0386a51SErik Pilkington    _LIBCPP_INLINE_VISIBILITY
226b0386a51SErik Pilkington    mapped_type& mapped() const
227b0386a51SErik Pilkington    {
228b0386a51SErik Pilkington        return static_cast<_Derived const*>(this)->
229b0386a51SErik Pilkington            __ptr_->__value_.__ref().second;
230b0386a51SErik Pilkington    }
231b0386a51SErik Pilkington};
232b0386a51SErik Pilkington
233b0386a51SErik Pilkingtontemplate <class _NodeType, class _Alloc>
234b0386a51SErik Pilkingtonusing __set_node_handle =
235b0386a51SErik Pilkington    __basic_node_handle< _NodeType, _Alloc, __set_node_handle_specifics>;
236b0386a51SErik Pilkington
237b0386a51SErik Pilkingtontemplate <class _NodeType, class _Alloc>
238b0386a51SErik Pilkingtonusing __map_node_handle =
239b0386a51SErik Pilkington    __basic_node_handle< _NodeType, _Alloc, __map_node_handle_specifics>;
240b0386a51SErik Pilkington
241b0386a51SErik Pilkingtontemplate <class _Iterator, class _NodeType>
2421be935f4SLouis Dionnestruct _LIBCPP_TEMPLATE_VIS __insert_return_type
243b0386a51SErik Pilkington{
244b0386a51SErik Pilkington    _Iterator position;
245b0386a51SErik Pilkington    bool inserted;
246b0386a51SErik Pilkington    _NodeType node;
247b0386a51SErik Pilkington};
248b0386a51SErik Pilkington
249b0386a51SErik Pilkington#endif // _LIBCPP_STD_VER > 14
250b0386a51SErik Pilkington
251b0386a51SErik Pilkington_LIBCPP_END_NAMESPACE_STD
252b0386a51SErik Pilkington
253e6972024SArthur O'Dwyer#endif  // _LIBCPP___NODE_HANDLE
254