1*9356374aSAndroid Build Coastguard Worker // Copyright 2018 The Abseil Authors. 2*9356374aSAndroid Build Coastguard Worker // 3*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); 4*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License. 5*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at 6*9356374aSAndroid Build Coastguard Worker // 7*9356374aSAndroid Build Coastguard Worker // https://www.apache.org/licenses/LICENSE-2.0 8*9356374aSAndroid Build Coastguard Worker // 9*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software 10*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, 11*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and 13*9356374aSAndroid Build Coastguard Worker // limitations under the License. 14*9356374aSAndroid Build Coastguard Worker 15*9356374aSAndroid Build Coastguard Worker #ifndef ABSL_CONTAINER_INTERNAL_COMMON_H_ 16*9356374aSAndroid Build Coastguard Worker #define ABSL_CONTAINER_INTERNAL_COMMON_H_ 17*9356374aSAndroid Build Coastguard Worker 18*9356374aSAndroid Build Coastguard Worker #include <cassert> 19*9356374aSAndroid Build Coastguard Worker #include <type_traits> 20*9356374aSAndroid Build Coastguard Worker 21*9356374aSAndroid Build Coastguard Worker #include "absl/meta/type_traits.h" 22*9356374aSAndroid Build Coastguard Worker #include "absl/types/optional.h" 23*9356374aSAndroid Build Coastguard Worker 24*9356374aSAndroid Build Coastguard Worker namespace absl { 25*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_BEGIN 26*9356374aSAndroid Build Coastguard Worker namespace container_internal { 27*9356374aSAndroid Build Coastguard Worker 28*9356374aSAndroid Build Coastguard Worker template <class, class = void> 29*9356374aSAndroid Build Coastguard Worker struct IsTransparent : std::false_type {}; 30*9356374aSAndroid Build Coastguard Worker template <class T> 31*9356374aSAndroid Build Coastguard Worker struct IsTransparent<T, absl::void_t<typename T::is_transparent>> 32*9356374aSAndroid Build Coastguard Worker : std::true_type {}; 33*9356374aSAndroid Build Coastguard Worker 34*9356374aSAndroid Build Coastguard Worker template <bool is_transparent> 35*9356374aSAndroid Build Coastguard Worker struct KeyArg { 36*9356374aSAndroid Build Coastguard Worker // Transparent. Forward `K`. 37*9356374aSAndroid Build Coastguard Worker template <typename K, typename key_type> 38*9356374aSAndroid Build Coastguard Worker using type = K; 39*9356374aSAndroid Build Coastguard Worker }; 40*9356374aSAndroid Build Coastguard Worker 41*9356374aSAndroid Build Coastguard Worker template <> 42*9356374aSAndroid Build Coastguard Worker struct KeyArg<false> { 43*9356374aSAndroid Build Coastguard Worker // Not transparent. Always use `key_type`. 44*9356374aSAndroid Build Coastguard Worker template <typename K, typename key_type> 45*9356374aSAndroid Build Coastguard Worker using type = key_type; 46*9356374aSAndroid Build Coastguard Worker }; 47*9356374aSAndroid Build Coastguard Worker 48*9356374aSAndroid Build Coastguard Worker // The node_handle concept from C++17. 49*9356374aSAndroid Build Coastguard Worker // We specialize node_handle for sets and maps. node_handle_base holds the 50*9356374aSAndroid Build Coastguard Worker // common API of both. 51*9356374aSAndroid Build Coastguard Worker template <typename PolicyTraits, typename Alloc> 52*9356374aSAndroid Build Coastguard Worker class node_handle_base { 53*9356374aSAndroid Build Coastguard Worker protected: 54*9356374aSAndroid Build Coastguard Worker using slot_type = typename PolicyTraits::slot_type; 55*9356374aSAndroid Build Coastguard Worker 56*9356374aSAndroid Build Coastguard Worker public: 57*9356374aSAndroid Build Coastguard Worker using allocator_type = Alloc; 58*9356374aSAndroid Build Coastguard Worker 59*9356374aSAndroid Build Coastguard Worker constexpr node_handle_base() = default; 60*9356374aSAndroid Build Coastguard Worker node_handle_base(node_handle_base&& other) noexcept { 61*9356374aSAndroid Build Coastguard Worker *this = std::move(other); 62*9356374aSAndroid Build Coastguard Worker } 63*9356374aSAndroid Build Coastguard Worker ~node_handle_base() { destroy(); } 64*9356374aSAndroid Build Coastguard Worker node_handle_base& operator=(node_handle_base&& other) noexcept { 65*9356374aSAndroid Build Coastguard Worker destroy(); 66*9356374aSAndroid Build Coastguard Worker if (!other.empty()) { 67*9356374aSAndroid Build Coastguard Worker alloc_ = other.alloc_; 68*9356374aSAndroid Build Coastguard Worker PolicyTraits::transfer(alloc(), slot(), other.slot()); 69*9356374aSAndroid Build Coastguard Worker other.reset(); 70*9356374aSAndroid Build Coastguard Worker } 71*9356374aSAndroid Build Coastguard Worker return *this; 72*9356374aSAndroid Build Coastguard Worker } 73*9356374aSAndroid Build Coastguard Worker 74*9356374aSAndroid Build Coastguard Worker bool empty() const noexcept { return !alloc_; } 75*9356374aSAndroid Build Coastguard Worker explicit operator bool() const noexcept { return !empty(); } 76*9356374aSAndroid Build Coastguard Worker allocator_type get_allocator() const { return *alloc_; } 77*9356374aSAndroid Build Coastguard Worker 78*9356374aSAndroid Build Coastguard Worker protected: 79*9356374aSAndroid Build Coastguard Worker friend struct CommonAccess; 80*9356374aSAndroid Build Coastguard Worker 81*9356374aSAndroid Build Coastguard Worker struct transfer_tag_t {}; 82*9356374aSAndroid Build Coastguard Worker node_handle_base(transfer_tag_t, const allocator_type& a, slot_type* s) 83*9356374aSAndroid Build Coastguard Worker : alloc_(a) { 84*9356374aSAndroid Build Coastguard Worker PolicyTraits::transfer(alloc(), slot(), s); 85*9356374aSAndroid Build Coastguard Worker } 86*9356374aSAndroid Build Coastguard Worker 87*9356374aSAndroid Build Coastguard Worker struct construct_tag_t {}; 88*9356374aSAndroid Build Coastguard Worker template <typename... Args> 89*9356374aSAndroid Build Coastguard Worker node_handle_base(construct_tag_t, const allocator_type& a, Args&&... args) 90*9356374aSAndroid Build Coastguard Worker : alloc_(a) { 91*9356374aSAndroid Build Coastguard Worker PolicyTraits::construct(alloc(), slot(), std::forward<Args>(args)...); 92*9356374aSAndroid Build Coastguard Worker } 93*9356374aSAndroid Build Coastguard Worker 94*9356374aSAndroid Build Coastguard Worker void destroy() { 95*9356374aSAndroid Build Coastguard Worker if (!empty()) { 96*9356374aSAndroid Build Coastguard Worker PolicyTraits::destroy(alloc(), slot()); 97*9356374aSAndroid Build Coastguard Worker reset(); 98*9356374aSAndroid Build Coastguard Worker } 99*9356374aSAndroid Build Coastguard Worker } 100*9356374aSAndroid Build Coastguard Worker 101*9356374aSAndroid Build Coastguard Worker void reset() { 102*9356374aSAndroid Build Coastguard Worker assert(alloc_.has_value()); 103*9356374aSAndroid Build Coastguard Worker alloc_ = absl::nullopt; 104*9356374aSAndroid Build Coastguard Worker } 105*9356374aSAndroid Build Coastguard Worker 106*9356374aSAndroid Build Coastguard Worker slot_type* slot() const { 107*9356374aSAndroid Build Coastguard Worker assert(!empty()); 108*9356374aSAndroid Build Coastguard Worker return reinterpret_cast<slot_type*>(std::addressof(slot_space_)); 109*9356374aSAndroid Build Coastguard Worker } 110*9356374aSAndroid Build Coastguard Worker allocator_type* alloc() { return std::addressof(*alloc_); } 111*9356374aSAndroid Build Coastguard Worker 112*9356374aSAndroid Build Coastguard Worker private: 113*9356374aSAndroid Build Coastguard Worker absl::optional<allocator_type> alloc_ = {}; 114*9356374aSAndroid Build Coastguard Worker alignas(slot_type) mutable unsigned char slot_space_[sizeof(slot_type)] = {}; 115*9356374aSAndroid Build Coastguard Worker }; 116*9356374aSAndroid Build Coastguard Worker 117*9356374aSAndroid Build Coastguard Worker // For sets. 118*9356374aSAndroid Build Coastguard Worker template <typename Policy, typename PolicyTraits, typename Alloc, 119*9356374aSAndroid Build Coastguard Worker typename = void> 120*9356374aSAndroid Build Coastguard Worker class node_handle : public node_handle_base<PolicyTraits, Alloc> { 121*9356374aSAndroid Build Coastguard Worker using Base = node_handle_base<PolicyTraits, Alloc>; 122*9356374aSAndroid Build Coastguard Worker 123*9356374aSAndroid Build Coastguard Worker public: 124*9356374aSAndroid Build Coastguard Worker using value_type = typename PolicyTraits::value_type; 125*9356374aSAndroid Build Coastguard Worker 126*9356374aSAndroid Build Coastguard Worker constexpr node_handle() {} 127*9356374aSAndroid Build Coastguard Worker 128*9356374aSAndroid Build Coastguard Worker value_type& value() const { return PolicyTraits::element(this->slot()); } 129*9356374aSAndroid Build Coastguard Worker 130*9356374aSAndroid Build Coastguard Worker private: 131*9356374aSAndroid Build Coastguard Worker friend struct CommonAccess; 132*9356374aSAndroid Build Coastguard Worker 133*9356374aSAndroid Build Coastguard Worker using Base::Base; 134*9356374aSAndroid Build Coastguard Worker }; 135*9356374aSAndroid Build Coastguard Worker 136*9356374aSAndroid Build Coastguard Worker // For maps. 137*9356374aSAndroid Build Coastguard Worker template <typename Policy, typename PolicyTraits, typename Alloc> 138*9356374aSAndroid Build Coastguard Worker class node_handle<Policy, PolicyTraits, Alloc, 139*9356374aSAndroid Build Coastguard Worker absl::void_t<typename Policy::mapped_type>> 140*9356374aSAndroid Build Coastguard Worker : public node_handle_base<PolicyTraits, Alloc> { 141*9356374aSAndroid Build Coastguard Worker using Base = node_handle_base<PolicyTraits, Alloc>; 142*9356374aSAndroid Build Coastguard Worker using slot_type = typename PolicyTraits::slot_type; 143*9356374aSAndroid Build Coastguard Worker 144*9356374aSAndroid Build Coastguard Worker public: 145*9356374aSAndroid Build Coastguard Worker using key_type = typename Policy::key_type; 146*9356374aSAndroid Build Coastguard Worker using mapped_type = typename Policy::mapped_type; 147*9356374aSAndroid Build Coastguard Worker 148*9356374aSAndroid Build Coastguard Worker constexpr node_handle() {} 149*9356374aSAndroid Build Coastguard Worker 150*9356374aSAndroid Build Coastguard Worker // When C++17 is available, we can use std::launder to provide mutable 151*9356374aSAndroid Build Coastguard Worker // access to the key. Otherwise, we provide const access. 152*9356374aSAndroid Build Coastguard Worker auto key() const 153*9356374aSAndroid Build Coastguard Worker -> decltype(PolicyTraits::mutable_key(std::declval<slot_type*>())) { 154*9356374aSAndroid Build Coastguard Worker return PolicyTraits::mutable_key(this->slot()); 155*9356374aSAndroid Build Coastguard Worker } 156*9356374aSAndroid Build Coastguard Worker 157*9356374aSAndroid Build Coastguard Worker mapped_type& mapped() const { 158*9356374aSAndroid Build Coastguard Worker return PolicyTraits::value(&PolicyTraits::element(this->slot())); 159*9356374aSAndroid Build Coastguard Worker } 160*9356374aSAndroid Build Coastguard Worker 161*9356374aSAndroid Build Coastguard Worker private: 162*9356374aSAndroid Build Coastguard Worker friend struct CommonAccess; 163*9356374aSAndroid Build Coastguard Worker 164*9356374aSAndroid Build Coastguard Worker using Base::Base; 165*9356374aSAndroid Build Coastguard Worker }; 166*9356374aSAndroid Build Coastguard Worker 167*9356374aSAndroid Build Coastguard Worker // Provide access to non-public node-handle functions. 168*9356374aSAndroid Build Coastguard Worker struct CommonAccess { 169*9356374aSAndroid Build Coastguard Worker template <typename Node> 170*9356374aSAndroid Build Coastguard Worker static auto GetSlot(const Node& node) -> decltype(node.slot()) { 171*9356374aSAndroid Build Coastguard Worker return node.slot(); 172*9356374aSAndroid Build Coastguard Worker } 173*9356374aSAndroid Build Coastguard Worker 174*9356374aSAndroid Build Coastguard Worker template <typename Node> 175*9356374aSAndroid Build Coastguard Worker static void Destroy(Node* node) { 176*9356374aSAndroid Build Coastguard Worker node->destroy(); 177*9356374aSAndroid Build Coastguard Worker } 178*9356374aSAndroid Build Coastguard Worker 179*9356374aSAndroid Build Coastguard Worker template <typename Node> 180*9356374aSAndroid Build Coastguard Worker static void Reset(Node* node) { 181*9356374aSAndroid Build Coastguard Worker node->reset(); 182*9356374aSAndroid Build Coastguard Worker } 183*9356374aSAndroid Build Coastguard Worker 184*9356374aSAndroid Build Coastguard Worker template <typename T, typename... Args> 185*9356374aSAndroid Build Coastguard Worker static T Transfer(Args&&... args) { 186*9356374aSAndroid Build Coastguard Worker return T(typename T::transfer_tag_t{}, std::forward<Args>(args)...); 187*9356374aSAndroid Build Coastguard Worker } 188*9356374aSAndroid Build Coastguard Worker 189*9356374aSAndroid Build Coastguard Worker template <typename T, typename... Args> 190*9356374aSAndroid Build Coastguard Worker static T Construct(Args&&... args) { 191*9356374aSAndroid Build Coastguard Worker return T(typename T::construct_tag_t{}, std::forward<Args>(args)...); 192*9356374aSAndroid Build Coastguard Worker } 193*9356374aSAndroid Build Coastguard Worker }; 194*9356374aSAndroid Build Coastguard Worker 195*9356374aSAndroid Build Coastguard Worker // Implement the insert_return_type<> concept of C++17. 196*9356374aSAndroid Build Coastguard Worker template <class Iterator, class NodeType> 197*9356374aSAndroid Build Coastguard Worker struct InsertReturnType { 198*9356374aSAndroid Build Coastguard Worker Iterator position; 199*9356374aSAndroid Build Coastguard Worker bool inserted; 200*9356374aSAndroid Build Coastguard Worker NodeType node; 201*9356374aSAndroid Build Coastguard Worker }; 202*9356374aSAndroid Build Coastguard Worker 203*9356374aSAndroid Build Coastguard Worker } // namespace container_internal 204*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_END 205*9356374aSAndroid Build Coastguard Worker } // namespace absl 206*9356374aSAndroid Build Coastguard Worker 207*9356374aSAndroid Build Coastguard Worker #endif // ABSL_CONTAINER_INTERNAL_COMMON_H_ 208