1 // Copyright 2018 The Abseil Authors.
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // https://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 #ifndef ABSL_CONTAINER_INTERNAL_CONTAINER_H_
16 #define ABSL_CONTAINER_INTERNAL_CONTAINER_H_
19 #include <type_traits>
21 #include "absl/meta/type_traits.h"
22 #include "absl/types/optional.h"
25 namespace container_internal {
27 template <class, class = void>
28 struct IsTransparent : std::false_type {};
30 struct IsTransparent<T, absl::void_t<typename T::is_transparent>>
33 template <bool is_transparent>
35 // Transparent. Forward `K`.
36 template <typename K, typename key_type>
41 struct KeyArg<false> {
42 // Not transparent. Always use `key_type`.
43 template <typename K, typename key_type>
44 using type = key_type;
47 // The node_handle concept from C++17.
48 // We specialize node_handle for sets and maps. node_handle_base holds the
49 // common API of both.
50 template <typename PolicyTraits, typename Alloc>
51 class node_handle_base {
53 using slot_type = typename PolicyTraits::slot_type;
56 using allocator_type = Alloc;
58 constexpr node_handle_base() {}
59 node_handle_base(node_handle_base&& other) noexcept {
60 *this = std::move(other);
62 ~node_handle_base() { destroy(); }
63 node_handle_base& operator=(node_handle_base&& other) noexcept {
66 alloc_ = other.alloc_;
67 PolicyTraits::transfer(alloc(), slot(), other.slot());
73 bool empty() const noexcept { return !alloc_; }
74 explicit operator bool() const noexcept { return !empty(); }
75 allocator_type get_allocator() const { return *alloc_; }
78 friend struct CommonAccess;
80 node_handle_base(const allocator_type& a, slot_type* s) : alloc_(a) {
81 PolicyTraits::transfer(alloc(), slot(), s);
86 PolicyTraits::destroy(alloc(), slot());
92 assert(alloc_.has_value());
93 alloc_ = absl::nullopt;
96 slot_type* slot() const {
98 return reinterpret_cast<slot_type*>(std::addressof(slot_space_));
100 allocator_type* alloc() { return std::addressof(*alloc_); }
103 absl::optional<allocator_type> alloc_;
104 mutable absl::aligned_storage_t<sizeof(slot_type), alignof(slot_type)>
109 template <typename Policy, typename PolicyTraits, typename Alloc,
111 class node_handle : public node_handle_base<PolicyTraits, Alloc> {
112 using Base = typename node_handle::node_handle_base;
115 using value_type = typename PolicyTraits::value_type;
117 constexpr node_handle() {}
119 value_type& value() const { return PolicyTraits::element(this->slot()); }
122 friend struct CommonAccess;
124 node_handle(const Alloc& a, typename Base::slot_type* s) : Base(a, s) {}
128 template <typename Policy, typename PolicyTraits, typename Alloc>
129 class node_handle<Policy, PolicyTraits, Alloc,
130 absl::void_t<typename Policy::mapped_type>>
131 : public node_handle_base<PolicyTraits, Alloc> {
132 using Base = typename node_handle::node_handle_base;
135 using key_type = typename Policy::key_type;
136 using mapped_type = typename Policy::mapped_type;
138 constexpr node_handle() {}
140 auto key() const -> decltype(PolicyTraits::key(this->slot())) {
141 return PolicyTraits::key(this->slot());
144 mapped_type& mapped() const {
145 return PolicyTraits::value(&PolicyTraits::element(this->slot()));
149 friend struct CommonAccess;
151 node_handle(const Alloc& a, typename Base::slot_type* s) : Base(a, s) {}
154 // Provide access to non-public node-handle functions.
155 struct CommonAccess {
156 template <typename Node>
157 static auto GetSlot(const Node& node) -> decltype(node.slot()) {
161 template <typename Node>
162 static void Reset(Node* node) {
166 template <typename T, typename... Args>
167 static T Make(Args&&... args) {
168 return T(std::forward<Args>(args)...);
172 // Implement the insert_return_type<> concept of C++17.
173 template <class Iterator, class NodeType>
174 struct InsertReturnType {
180 } // namespace container_internal
183 #endif // ABSL_CONTAINER_INTERNAL_CONTAINER_H_