// Copyright 2018 The Abseil Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef ABSL_CONTAINER_INTERNAL_CONTAINER_H_ #define ABSL_CONTAINER_INTERNAL_CONTAINER_H_ #include #include #include "absl/meta/type_traits.h" #include "absl/types/optional.h" namespace absl { ABSL_NAMESPACE_BEGIN namespace container_internal { template struct IsTransparent : std::false_type {}; template struct IsTransparent> : std::true_type {}; template struct KeyArg { // Transparent. Forward `K`. template using type = K; }; template <> struct KeyArg { // Not transparent. Always use `key_type`. template using type = key_type; }; // The node_handle concept from C++17. // We specialize node_handle for sets and maps. node_handle_base holds the // common API of both. template class node_handle_base { protected: using slot_type = typename PolicyTraits::slot_type; public: using allocator_type = Alloc; constexpr node_handle_base() {} node_handle_base(node_handle_base&& other) noexcept { *this = std::move(other); } ~node_handle_base() { destroy(); } node_handle_base& operator=(node_handle_base&& other) noexcept { destroy(); if (!other.empty()) { alloc_ = other.alloc_; PolicyTraits::transfer(alloc(), slot(), other.slot()); other.reset(); } return *this; } bool empty() const noexcept { return !alloc_; } explicit operator bool() const noexcept { return !empty(); } allocator_type get_allocator() const { return *alloc_; } protected: friend struct CommonAccess; struct transfer_tag_t {}; node_handle_base(transfer_tag_t, const allocator_type& a, slot_type* s) : alloc_(a) { PolicyTraits::transfer(alloc(), slot(), s); } struct move_tag_t {}; node_handle_base(move_tag_t, const allocator_type& a, slot_type* s) : alloc_(a) { PolicyTraits::construct(alloc(), slot(), s); } void destroy() { if (!empty()) { PolicyTraits::destroy(alloc(), slot()); reset(); } } void reset() { assert(alloc_.has_value()); alloc_ = absl::nullopt; } slot_type* slot() const { assert(!empty()); return reinterpret_cast(std::addressof(slot_space_)); } allocator_type* alloc() { return std::addressof(*alloc_); } private: absl::optional alloc_; mutable absl::aligned_storage_t slot_space_; }; // For sets. template class node_handle : public node_handle_base { using Base = node_handle_base; public: using value_type = typename PolicyTraits::value_type; constexpr node_handle() {} value_type& value() const { return PolicyTraits::element(this->slot()); } private: friend struct CommonAccess; using Base::Base; }; // For maps. template class node_handle> : public node_handle_base { using Base = node_handle_base; public: using key_type = typename Policy::key_type; using mapped_type = typename Policy::mapped_type; constexpr node_handle() {} auto key() const -> decltype(PolicyTraits::key(this->slot())) { return PolicyTraits::key(this->slot()); } mapped_type& mapped() const { return PolicyTraits::value(&PolicyTraits::element(this->slot())); } private: friend struct CommonAccess; using Base::Base; }; // Provide access to non-public node-handle functions. struct CommonAccess { template static auto GetSlot(const Node& node) -> decltype(node.slot()) { return node.slot(); } template static void Destroy(Node* node) { node->destroy(); } template static void Reset(Node* node) { node->reset(); } template static T Transfer(Args&&... args) { return T(typename T::transfer_tag_t{}, std::forward(args)...); } template static T Move(Args&&... args) { return T(typename T::move_tag_t{}, std::forward(args)...); } }; // Implement the insert_return_type<> concept of C++17. template struct InsertReturnType { Iterator position; bool inserted; NodeType node; }; } // namespace container_internal ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_INTERNAL_CONTAINER_H_