138fd1498Szrj // Node handles for containers -*- C++ -*-
238fd1498Szrj
338fd1498Szrj // Copyright (C) 2016-2018 Free Software Foundation, Inc.
438fd1498Szrj //
538fd1498Szrj // This file is part of the GNU ISO C++ Library. This library is free
638fd1498Szrj // software; you can redistribute it and/or modify it under the
738fd1498Szrj // terms of the GNU General Public License as published by the
838fd1498Szrj // Free Software Foundation; either version 3, or (at your option)
938fd1498Szrj // any later version.
1038fd1498Szrj
1138fd1498Szrj // This library is distributed in the hope that it will be useful,
1238fd1498Szrj // but WITHOUT ANY WARRANTY; without even the implied warranty of
1338fd1498Szrj // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1438fd1498Szrj // GNU General Public License for more details.
1538fd1498Szrj
1638fd1498Szrj // Under Section 7 of GPL version 3, you are granted additional
1738fd1498Szrj // permissions described in the GCC Runtime Library Exception, version
1838fd1498Szrj // 3.1, as published by the Free Software Foundation.
1938fd1498Szrj
2038fd1498Szrj // You should have received a copy of the GNU General Public License and
2138fd1498Szrj // a copy of the GCC Runtime Library Exception along with this program;
2238fd1498Szrj // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
2338fd1498Szrj // <http://www.gnu.org/licenses/>.
2438fd1498Szrj
2538fd1498Szrj /** @file bits/node_handle.h
2638fd1498Szrj * This is an internal header file, included by other library headers.
2738fd1498Szrj * Do not attempt to use it directly.
2838fd1498Szrj * @headername{map,set,unordered_map,unordered_set}
2938fd1498Szrj */
3038fd1498Szrj
3138fd1498Szrj #ifndef _NODE_HANDLE
3238fd1498Szrj #define _NODE_HANDLE 1
3338fd1498Szrj
3438fd1498Szrj #pragma GCC system_header
3538fd1498Szrj
3638fd1498Szrj #if __cplusplus > 201402L
3738fd1498Szrj # define __cpp_lib_node_extract 201606
3838fd1498Szrj
3938fd1498Szrj #include <optional>
4038fd1498Szrj #include <bits/alloc_traits.h>
4138fd1498Szrj #include <bits/ptr_traits.h>
4238fd1498Szrj
_GLIBCXX_VISIBILITY(default)4338fd1498Szrj namespace std _GLIBCXX_VISIBILITY(default)
4438fd1498Szrj {
4538fd1498Szrj _GLIBCXX_BEGIN_NAMESPACE_VERSION
4638fd1498Szrj
4738fd1498Szrj /// Base class for node handle types of maps and sets.
4838fd1498Szrj template<typename _Val, typename _NodeAlloc>
4938fd1498Szrj class _Node_handle_common
5038fd1498Szrj {
5138fd1498Szrj using _AllocTraits = allocator_traits<_NodeAlloc>;
5238fd1498Szrj
5338fd1498Szrj public:
5438fd1498Szrj using allocator_type = __alloc_rebind<_NodeAlloc, _Val>;
5538fd1498Szrj
5638fd1498Szrj allocator_type
5738fd1498Szrj get_allocator() const noexcept
5838fd1498Szrj {
5938fd1498Szrj __glibcxx_assert(!this->empty());
6038fd1498Szrj return allocator_type(*_M_alloc);
6138fd1498Szrj }
6238fd1498Szrj
6338fd1498Szrj explicit operator bool() const noexcept { return _M_ptr != nullptr; }
6438fd1498Szrj
6538fd1498Szrj [[nodiscard]] bool empty() const noexcept { return _M_ptr == nullptr; }
6638fd1498Szrj
6738fd1498Szrj protected:
6838fd1498Szrj constexpr _Node_handle_common() noexcept : _M_ptr(), _M_alloc() {}
6938fd1498Szrj
7038fd1498Szrj ~_Node_handle_common() { _M_destroy(); }
7138fd1498Szrj
7238fd1498Szrj _Node_handle_common(_Node_handle_common&& __nh) noexcept
7338fd1498Szrj : _M_ptr(__nh._M_ptr), _M_alloc(std::move(__nh._M_alloc))
7438fd1498Szrj {
7538fd1498Szrj __nh._M_ptr = nullptr;
7638fd1498Szrj __nh._M_alloc = nullopt;
7738fd1498Szrj }
7838fd1498Szrj
7938fd1498Szrj _Node_handle_common&
8038fd1498Szrj operator=(_Node_handle_common&& __nh) noexcept
8138fd1498Szrj {
8238fd1498Szrj _M_destroy();
8338fd1498Szrj _M_ptr = __nh._M_ptr;
8438fd1498Szrj if constexpr (is_move_assignable_v<_NodeAlloc>)
8538fd1498Szrj {
8638fd1498Szrj if (_AllocTraits::propagate_on_container_move_assignment::value
8738fd1498Szrj || !this->_M_alloc)
8838fd1498Szrj this->_M_alloc = std::move(__nh._M_alloc);
8938fd1498Szrj else
9038fd1498Szrj {
9138fd1498Szrj __glibcxx_assert(this->_M_alloc == __nh._M_alloc);
9238fd1498Szrj }
9338fd1498Szrj }
9438fd1498Szrj else
9538fd1498Szrj {
9638fd1498Szrj __glibcxx_assert(_M_alloc);
9738fd1498Szrj }
9838fd1498Szrj __nh._M_ptr = nullptr;
9938fd1498Szrj __nh._M_alloc = nullopt;
10038fd1498Szrj return *this;
10138fd1498Szrj }
10238fd1498Szrj
10338fd1498Szrj _Node_handle_common(typename _AllocTraits::pointer __ptr,
10438fd1498Szrj const _NodeAlloc& __alloc)
10538fd1498Szrj : _M_ptr(__ptr), _M_alloc(__alloc) { }
10638fd1498Szrj
10738fd1498Szrj void
10838fd1498Szrj _M_swap(_Node_handle_common& __nh) noexcept
10938fd1498Szrj {
11038fd1498Szrj using std::swap;
11138fd1498Szrj swap(_M_ptr, __nh._M_ptr);
112*58e805e6Szrj if (_AllocTraits::propagate_on_container_swap::value
11338fd1498Szrj || !_M_alloc || !__nh._M_alloc)
11438fd1498Szrj _M_alloc.swap(__nh._M_alloc);
11538fd1498Szrj else
11638fd1498Szrj {
11738fd1498Szrj __glibcxx_assert(_M_alloc == __nh._M_alloc);
11838fd1498Szrj }
11938fd1498Szrj }
12038fd1498Szrj
12138fd1498Szrj private:
12238fd1498Szrj void
12338fd1498Szrj _M_destroy() noexcept
12438fd1498Szrj {
12538fd1498Szrj if (_M_ptr != nullptr)
12638fd1498Szrj {
12738fd1498Szrj allocator_type __alloc(*_M_alloc);
12838fd1498Szrj allocator_traits<allocator_type>::destroy(__alloc,
12938fd1498Szrj _M_ptr->_M_valptr());
13038fd1498Szrj _AllocTraits::deallocate(*_M_alloc, _M_ptr, 1);
13138fd1498Szrj }
13238fd1498Szrj }
13338fd1498Szrj
13438fd1498Szrj protected:
13538fd1498Szrj typename _AllocTraits::pointer _M_ptr;
13638fd1498Szrj private:
13738fd1498Szrj optional<_NodeAlloc> _M_alloc;
13838fd1498Szrj
13938fd1498Szrj template<typename _Key2, typename _Value2, typename _KeyOfValue,
14038fd1498Szrj typename _Compare, typename _ValueAlloc>
14138fd1498Szrj friend class _Rb_tree;
14238fd1498Szrj };
14338fd1498Szrj
14438fd1498Szrj /// Node handle type for maps.
14538fd1498Szrj template<typename _Key, typename _Value, typename _NodeAlloc>
14638fd1498Szrj class _Node_handle : public _Node_handle_common<_Value, _NodeAlloc>
14738fd1498Szrj {
14838fd1498Szrj public:
14938fd1498Szrj constexpr _Node_handle() noexcept = default;
15038fd1498Szrj ~_Node_handle() = default;
15138fd1498Szrj _Node_handle(_Node_handle&&) noexcept = default;
15238fd1498Szrj
15338fd1498Szrj _Node_handle&
15438fd1498Szrj operator=(_Node_handle&&) noexcept = default;
15538fd1498Szrj
15638fd1498Szrj using key_type = _Key;
15738fd1498Szrj using mapped_type = typename _Value::second_type;
15838fd1498Szrj
15938fd1498Szrj key_type&
16038fd1498Szrj key() const noexcept
16138fd1498Szrj {
16238fd1498Szrj __glibcxx_assert(!this->empty());
16338fd1498Szrj return *_M_pkey;
16438fd1498Szrj }
16538fd1498Szrj
16638fd1498Szrj mapped_type&
16738fd1498Szrj mapped() const noexcept
16838fd1498Szrj {
16938fd1498Szrj __glibcxx_assert(!this->empty());
17038fd1498Szrj return *_M_pmapped;
17138fd1498Szrj }
17238fd1498Szrj
17338fd1498Szrj void
17438fd1498Szrj swap(_Node_handle& __nh) noexcept
17538fd1498Szrj {
17638fd1498Szrj this->_M_swap(__nh);
17738fd1498Szrj using std::swap;
17838fd1498Szrj swap(_M_pkey, __nh._M_pkey);
17938fd1498Szrj swap(_M_pmapped, __nh._M_pmapped);
18038fd1498Szrj }
18138fd1498Szrj
18238fd1498Szrj friend void
18338fd1498Szrj swap(_Node_handle& __x, _Node_handle& __y)
18438fd1498Szrj noexcept(noexcept(__x.swap(__y)))
18538fd1498Szrj { __x.swap(__y); }
18638fd1498Szrj
18738fd1498Szrj private:
18838fd1498Szrj using _AllocTraits = allocator_traits<_NodeAlloc>;
18938fd1498Szrj
19038fd1498Szrj _Node_handle(typename _AllocTraits::pointer __ptr,
19138fd1498Szrj const _NodeAlloc& __alloc)
19238fd1498Szrj : _Node_handle_common<_Value, _NodeAlloc>(__ptr, __alloc)
19338fd1498Szrj {
19438fd1498Szrj if (__ptr)
19538fd1498Szrj {
19638fd1498Szrj auto& __key = const_cast<_Key&>(__ptr->_M_valptr()->first);
19738fd1498Szrj _M_pkey = _S_pointer_to(__key);
19838fd1498Szrj _M_pmapped = _S_pointer_to(__ptr->_M_valptr()->second);
19938fd1498Szrj }
20038fd1498Szrj else
20138fd1498Szrj {
20238fd1498Szrj _M_pkey = nullptr;
20338fd1498Szrj _M_pmapped = nullptr;
20438fd1498Szrj }
20538fd1498Szrj }
20638fd1498Szrj
20738fd1498Szrj template<typename _Tp>
20838fd1498Szrj using __pointer
20938fd1498Szrj = __ptr_rebind<typename _AllocTraits::pointer,
21038fd1498Szrj remove_reference_t<_Tp>>;
21138fd1498Szrj
21238fd1498Szrj __pointer<_Key> _M_pkey = nullptr;
21338fd1498Szrj __pointer<typename _Value::second_type> _M_pmapped = nullptr;
21438fd1498Szrj
21538fd1498Szrj template<typename _Tp>
21638fd1498Szrj __pointer<_Tp>
21738fd1498Szrj _S_pointer_to(_Tp& __obj)
21838fd1498Szrj { return pointer_traits<__pointer<_Tp>>::pointer_to(__obj); }
21938fd1498Szrj
22038fd1498Szrj const key_type&
22138fd1498Szrj _M_key() const noexcept { return key(); }
22238fd1498Szrj
22338fd1498Szrj template<typename _Key2, typename _Value2, typename _KeyOfValue,
22438fd1498Szrj typename _Compare, typename _ValueAlloc>
22538fd1498Szrj friend class _Rb_tree;
22638fd1498Szrj
22738fd1498Szrj template<typename _Key2, typename _Value2, typename _ValueAlloc,
22838fd1498Szrj typename _ExtractKey, typename _Equal,
22938fd1498Szrj typename _H1, typename _H2, typename _Hash,
23038fd1498Szrj typename _RehashPolicy, typename _Traits>
23138fd1498Szrj friend class _Hashtable;
23238fd1498Szrj };
23338fd1498Szrj
23438fd1498Szrj /// Node handle type for sets.
23538fd1498Szrj template<typename _Value, typename _NodeAlloc>
23638fd1498Szrj class _Node_handle<_Value, _Value, _NodeAlloc>
23738fd1498Szrj : public _Node_handle_common<_Value, _NodeAlloc>
23838fd1498Szrj {
23938fd1498Szrj public:
24038fd1498Szrj constexpr _Node_handle() noexcept = default;
24138fd1498Szrj ~_Node_handle() = default;
24238fd1498Szrj _Node_handle(_Node_handle&&) noexcept = default;
24338fd1498Szrj
24438fd1498Szrj _Node_handle&
24538fd1498Szrj operator=(_Node_handle&&) noexcept = default;
24638fd1498Szrj
24738fd1498Szrj using value_type = _Value;
24838fd1498Szrj
24938fd1498Szrj value_type&
25038fd1498Szrj value() const noexcept
25138fd1498Szrj {
25238fd1498Szrj __glibcxx_assert(!this->empty());
25338fd1498Szrj return *this->_M_ptr->_M_valptr();
25438fd1498Szrj }
25538fd1498Szrj
25638fd1498Szrj void
25738fd1498Szrj swap(_Node_handle& __nh) noexcept
25838fd1498Szrj { this->_M_swap(__nh); }
25938fd1498Szrj
26038fd1498Szrj friend void
26138fd1498Szrj swap(_Node_handle& __x, _Node_handle& __y)
26238fd1498Szrj noexcept(noexcept(__x.swap(__y)))
26338fd1498Szrj { __x.swap(__y); }
26438fd1498Szrj
26538fd1498Szrj private:
26638fd1498Szrj using _AllocTraits = allocator_traits<_NodeAlloc>;
26738fd1498Szrj
26838fd1498Szrj _Node_handle(typename _AllocTraits::pointer __ptr,
26938fd1498Szrj const _NodeAlloc& __alloc)
27038fd1498Szrj : _Node_handle_common<_Value, _NodeAlloc>(__ptr, __alloc) { }
27138fd1498Szrj
27238fd1498Szrj const value_type&
27338fd1498Szrj _M_key() const noexcept { return value(); }
27438fd1498Szrj
27538fd1498Szrj template<typename _Key, typename _Val, typename _KeyOfValue,
27638fd1498Szrj typename _Compare, typename _Alloc>
27738fd1498Szrj friend class _Rb_tree;
27838fd1498Szrj
27938fd1498Szrj template<typename _Key2, typename _Value2, typename _ValueAlloc,
28038fd1498Szrj typename _ExtractKey, typename _Equal,
28138fd1498Szrj typename _H1, typename _H2, typename _Hash,
28238fd1498Szrj typename _RehashPolicy, typename _Traits>
28338fd1498Szrj friend class _Hashtable;
28438fd1498Szrj };
28538fd1498Szrj
28638fd1498Szrj /// Return type of insert(node_handle&&) on unique maps/sets.
28738fd1498Szrj template<typename _Iterator, typename _NodeHandle>
28838fd1498Szrj struct _Node_insert_return
28938fd1498Szrj {
29038fd1498Szrj _Iterator position = _Iterator();
29138fd1498Szrj bool inserted = false;
29238fd1498Szrj _NodeHandle node;
29338fd1498Szrj };
29438fd1498Szrj
29538fd1498Szrj _GLIBCXX_END_NAMESPACE_VERSION
29638fd1498Szrj } // namespace std
29738fd1498Szrj
29838fd1498Szrj #endif // C++17
29938fd1498Szrj #endif
300