Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:27:10

0001 // Copyright 2018 The Abseil Authors.
0002 //
0003 // Licensed under the Apache License, Version 2.0 (the "License");
0004 // you may not use this file except in compliance with the License.
0005 // You may obtain a copy of the License at
0006 //
0007 //      https://www.apache.org/licenses/LICENSE-2.0
0008 //
0009 // Unless required by applicable law or agreed to in writing, software
0010 // distributed under the License is distributed on an "AS IS" BASIS,
0011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0012 // See the License for the specific language governing permissions and
0013 // limitations under the License.
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   // Transparent. Forward `K`.
0037   template <typename K, typename key_type>
0038   using type = K;
0039 };
0040 
0041 template <>
0042 struct KeyArg<false> {
0043   // Not transparent. Always use `key_type`.
0044   template <typename K, typename key_type>
0045   using type = key_type;
0046 };
0047 
0048 // The node_handle concept from C++17.
0049 // We specialize node_handle for sets and maps. node_handle_base holds the
0050 // common API of both.
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 // For sets.
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 // For maps.
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   // When C++17 is available, we can use std::launder to provide mutable
0151   // access to the key. Otherwise, we provide const access.
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 // Provide access to non-public node-handle functions.
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 // Implement the insert_return_type<> concept of C++17.
0196 template <class Iterator, class NodeType>
0197 struct InsertReturnType {
0198   Iterator position;
0199   bool inserted;
0200   NodeType node;
0201 };
0202 
0203 }  // namespace container_internal
0204 ABSL_NAMESPACE_END
0205 }  // namespace absl
0206 
0207 #endif  // ABSL_CONTAINER_INTERNAL_COMMON_H_