File indexing completed on 2025-01-18 09:27:10
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef ABSL_CONTAINER_INTERNAL_COMMON_H_
0016 #define ABSL_CONTAINER_INTERNAL_COMMON_H_
0017
0018 #include <cassert>
0019 #include <type_traits>
0020
0021 #include "absl/meta/type_traits.h"
0022 #include "absl/types/optional.h"
0023
0024 namespace absl {
0025 ABSL_NAMESPACE_BEGIN
0026 namespace container_internal {
0027
0028 template <class, class = void>
0029 struct IsTransparent : std::false_type {};
0030 template <class T>
0031 struct IsTransparent<T, absl::void_t<typename T::is_transparent>>
0032 : std::true_type {};
0033
0034 template <bool is_transparent>
0035 struct KeyArg {
0036
0037 template <typename K, typename key_type>
0038 using type = K;
0039 };
0040
0041 template <>
0042 struct KeyArg<false> {
0043
0044 template <typename K, typename key_type>
0045 using type = key_type;
0046 };
0047
0048
0049
0050
0051 template <typename PolicyTraits, typename Alloc>
0052 class node_handle_base {
0053 protected:
0054 using slot_type = typename PolicyTraits::slot_type;
0055
0056 public:
0057 using allocator_type = Alloc;
0058
0059 constexpr node_handle_base() = default;
0060 node_handle_base(node_handle_base&& other) noexcept {
0061 *this = std::move(other);
0062 }
0063 ~node_handle_base() { destroy(); }
0064 node_handle_base& operator=(node_handle_base&& other) noexcept {
0065 destroy();
0066 if (!other.empty()) {
0067 alloc_ = other.alloc_;
0068 PolicyTraits::transfer(alloc(), slot(), other.slot());
0069 other.reset();
0070 }
0071 return *this;
0072 }
0073
0074 bool empty() const noexcept { return !alloc_; }
0075 explicit operator bool() const noexcept { return !empty(); }
0076 allocator_type get_allocator() const { return *alloc_; }
0077
0078 protected:
0079 friend struct CommonAccess;
0080
0081 struct transfer_tag_t {};
0082 node_handle_base(transfer_tag_t, const allocator_type& a, slot_type* s)
0083 : alloc_(a) {
0084 PolicyTraits::transfer(alloc(), slot(), s);
0085 }
0086
0087 struct construct_tag_t {};
0088 template <typename... Args>
0089 node_handle_base(construct_tag_t, const allocator_type& a, Args&&... args)
0090 : alloc_(a) {
0091 PolicyTraits::construct(alloc(), slot(), std::forward<Args>(args)...);
0092 }
0093
0094 void destroy() {
0095 if (!empty()) {
0096 PolicyTraits::destroy(alloc(), slot());
0097 reset();
0098 }
0099 }
0100
0101 void reset() {
0102 assert(alloc_.has_value());
0103 alloc_ = absl::nullopt;
0104 }
0105
0106 slot_type* slot() const {
0107 assert(!empty());
0108 return reinterpret_cast<slot_type*>(std::addressof(slot_space_));
0109 }
0110 allocator_type* alloc() { return std::addressof(*alloc_); }
0111
0112 private:
0113 absl::optional<allocator_type> alloc_ = {};
0114 alignas(slot_type) mutable unsigned char slot_space_[sizeof(slot_type)] = {};
0115 };
0116
0117
0118 template <typename Policy, typename PolicyTraits, typename Alloc,
0119 typename = void>
0120 class node_handle : public node_handle_base<PolicyTraits, Alloc> {
0121 using Base = node_handle_base<PolicyTraits, Alloc>;
0122
0123 public:
0124 using value_type = typename PolicyTraits::value_type;
0125
0126 constexpr node_handle() {}
0127
0128 value_type& value() const { return PolicyTraits::element(this->slot()); }
0129
0130 private:
0131 friend struct CommonAccess;
0132
0133 using Base::Base;
0134 };
0135
0136
0137 template <typename Policy, typename PolicyTraits, typename Alloc>
0138 class node_handle<Policy, PolicyTraits, Alloc,
0139 absl::void_t<typename Policy::mapped_type>>
0140 : public node_handle_base<PolicyTraits, Alloc> {
0141 using Base = node_handle_base<PolicyTraits, Alloc>;
0142 using slot_type = typename PolicyTraits::slot_type;
0143
0144 public:
0145 using key_type = typename Policy::key_type;
0146 using mapped_type = typename Policy::mapped_type;
0147
0148 constexpr node_handle() {}
0149
0150
0151
0152 auto key() const
0153 -> decltype(PolicyTraits::mutable_key(std::declval<slot_type*>())) {
0154 return PolicyTraits::mutable_key(this->slot());
0155 }
0156
0157 mapped_type& mapped() const {
0158 return PolicyTraits::value(&PolicyTraits::element(this->slot()));
0159 }
0160
0161 private:
0162 friend struct CommonAccess;
0163
0164 using Base::Base;
0165 };
0166
0167
0168 struct CommonAccess {
0169 template <typename Node>
0170 static auto GetSlot(const Node& node) -> decltype(node.slot()) {
0171 return node.slot();
0172 }
0173
0174 template <typename Node>
0175 static void Destroy(Node* node) {
0176 node->destroy();
0177 }
0178
0179 template <typename Node>
0180 static void Reset(Node* node) {
0181 node->reset();
0182 }
0183
0184 template <typename T, typename... Args>
0185 static T Transfer(Args&&... args) {
0186 return T(typename T::transfer_tag_t{}, std::forward<Args>(args)...);
0187 }
0188
0189 template <typename T, typename... Args>
0190 static T Construct(Args&&... args) {
0191 return T(typename T::construct_tag_t{}, std::forward<Args>(args)...);
0192 }
0193 };
0194
0195
0196 template <class Iterator, class NodeType>
0197 struct InsertReturnType {
0198 Iterator position;
0199 bool inserted;
0200 NodeType node;
0201 };
0202
0203 }
0204 ABSL_NAMESPACE_END
0205 }
0206
0207 #endif