Home | History | Annotate | Download | only in include
      1 // -*- C++ -*-
      2 //===----------------------------------------------------------------------===//
      3 //
      4 //                     The LLVM Compiler Infrastructure
      5 //
      6 // This file is dual licensed under the MIT and the University of Illinois Open
      7 // Source Licenses. See LICENSE.TXT for details.
      8 //
      9 //===----------------------------------------------------------------------===//
     10 
     11 #ifndef _LIBCPP___NODE_HANDLE
     12 #define _LIBCPP___NODE_HANDLE
     13 
     14 #include <__config>
     15 #include <memory>
     16 #include <optional>
     17 
     18 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
     19 #pragma GCC system_header
     20 #endif
     21 
     22 _LIBCPP_PUSH_MACROS
     23 #include <__undef_macros>
     24 
     25 _LIBCPP_BEGIN_NAMESPACE_STD
     26 
     27 #if _LIBCPP_STD_VER > 14
     28 
     29 // Specialized in __tree & __hash_table for their _NodeType.
     30 template <class _NodeType, class _Alloc>
     31 struct __generic_container_node_destructor;
     32 
     33 template <class _NodeType, class _Alloc,
     34           template <class, class> class _MapOrSetSpecifics>
     35 class _LIBCPP_TEMPLATE_VIS __basic_node_handle
     36     : public _MapOrSetSpecifics<
     37           _NodeType,
     38           __basic_node_handle<_NodeType, _Alloc, _MapOrSetSpecifics>>
     39 {
     40     template <class _Tp, class _Compare, class _Allocator>
     41         friend class __tree;
     42     template <class _Tp, class _Hash, class _Equal, class _Allocator>
     43         friend class __hash_table;
     44     friend struct _MapOrSetSpecifics<
     45         _NodeType, __basic_node_handle<_NodeType, _Alloc, _MapOrSetSpecifics>>;
     46 
     47     typedef allocator_traits<_Alloc> __alloc_traits;
     48     typedef typename __rebind_pointer<typename __alloc_traits::void_pointer,
     49                                       _NodeType>::type
     50         __node_pointer_type;
     51 
     52 public:
     53     typedef _Alloc allocator_type;
     54 
     55 private:
     56     __node_pointer_type __ptr_ = nullptr;
     57     optional<allocator_type> __alloc_;
     58 
     59     _LIBCPP_INLINE_VISIBILITY
     60     void __release()
     61     {
     62         __ptr_ = nullptr;
     63         __alloc_ = _VSTD::nullopt;
     64     }
     65 
     66     _LIBCPP_INLINE_VISIBILITY
     67     void __destroy_node_pointer()
     68     {
     69         if (__ptr_ != nullptr)
     70         {
     71             typedef typename __allocator_traits_rebind<
     72                 allocator_type, _NodeType>::type __node_alloc_type;
     73             __node_alloc_type __alloc(*__alloc_);
     74             __generic_container_node_destructor<_NodeType, __node_alloc_type>(
     75                 __alloc, true)(__ptr_);
     76             __ptr_ = nullptr;
     77         }
     78     }
     79 
     80     _LIBCPP_INLINE_VISIBILITY
     81     __basic_node_handle(__node_pointer_type __ptr,
     82                         allocator_type const& __alloc)
     83             : __ptr_(__ptr), __alloc_(__alloc)
     84     {
     85     }
     86 
     87 public:
     88     _LIBCPP_INLINE_VISIBILITY
     89     __basic_node_handle() = default;
     90 
     91     _LIBCPP_INLINE_VISIBILITY
     92     __basic_node_handle(__basic_node_handle&& __other) noexcept
     93             : __ptr_(__other.__ptr_),
     94               __alloc_(_VSTD::move(__other.__alloc_))
     95     {
     96         __other.__ptr_ = nullptr;
     97         __other.__alloc_ = _VSTD::nullopt;
     98     }
     99 
    100     _LIBCPP_INLINE_VISIBILITY
    101     __basic_node_handle& operator=(__basic_node_handle&& __other)
    102     {
    103         _LIBCPP_ASSERT(
    104             __alloc_ == _VSTD::nullopt ||
    105             __alloc_traits::propagate_on_container_move_assignment::value ||
    106             __alloc_ == __other.__alloc_,
    107             "node_type with incompatible allocator passed to "
    108             "node_type::operator=(node_type&&)");
    109 
    110         __destroy_node_pointer();
    111         __ptr_ = __other.__ptr_;
    112 
    113         if (__alloc_traits::propagate_on_container_move_assignment::value ||
    114             __alloc_ == _VSTD::nullopt)
    115             __alloc_ = _VSTD::move(__other.__alloc_);
    116 
    117         __other.__ptr_ = nullptr;
    118         __other.__alloc_ = _VSTD::nullopt;
    119 
    120         return *this;
    121     }
    122 
    123     _LIBCPP_INLINE_VISIBILITY
    124     allocator_type get_allocator() const { return *__alloc_; }
    125 
    126     _LIBCPP_INLINE_VISIBILITY
    127     explicit operator bool() const { return __ptr_ != nullptr; }
    128 
    129     _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
    130     bool empty() const { return __ptr_ == nullptr; }
    131 
    132     _LIBCPP_INLINE_VISIBILITY
    133     void swap(__basic_node_handle& __other) noexcept(
    134         __alloc_traits::propagate_on_container_swap::value ||
    135         __alloc_traits::is_always_equal::value)
    136     {
    137         using _VSTD::swap;
    138         swap(__ptr_, __other.__ptr_);
    139         if (__alloc_traits::propagate_on_container_swap::value ||
    140             __alloc_ == _VSTD::nullopt || __other.__alloc_ == _VSTD::nullopt)
    141             swap(__alloc_, __other.__alloc_);
    142     }
    143 
    144     _LIBCPP_INLINE_VISIBILITY
    145     friend void swap(__basic_node_handle& __a, __basic_node_handle& __b)
    146         noexcept(noexcept(__a.swap(__b))) { __a.swap(__b); }
    147 
    148     _LIBCPP_INLINE_VISIBILITY
    149     ~__basic_node_handle()
    150     {
    151         __destroy_node_pointer();
    152     }
    153 };
    154 
    155 template <class _NodeType, class _Derived>
    156 struct __set_node_handle_specifics
    157 {
    158     typedef typename _NodeType::__node_value_type value_type;
    159 
    160     _LIBCPP_INLINE_VISIBILITY
    161     value_type& value() const
    162     {
    163         return static_cast<_Derived const*>(this)->__ptr_->__value_;
    164     }
    165 };
    166 
    167 template <class _NodeType, class _Derived>
    168 struct __map_node_handle_specifics
    169 {
    170     typedef typename _NodeType::__node_value_type::key_type key_type;
    171     typedef typename _NodeType::__node_value_type::mapped_type mapped_type;
    172 
    173     _LIBCPP_INLINE_VISIBILITY
    174     key_type& key() const
    175     {
    176         return static_cast<_Derived const*>(this)->
    177             __ptr_->__value_.__ref().first;
    178     }
    179 
    180     _LIBCPP_INLINE_VISIBILITY
    181     mapped_type& mapped() const
    182     {
    183         return static_cast<_Derived const*>(this)->
    184             __ptr_->__value_.__ref().second;
    185     }
    186 };
    187 
    188 template <class _NodeType, class _Alloc>
    189 using __set_node_handle =
    190     __basic_node_handle< _NodeType, _Alloc, __set_node_handle_specifics>;
    191 
    192 template <class _NodeType, class _Alloc>
    193 using __map_node_handle =
    194     __basic_node_handle< _NodeType, _Alloc, __map_node_handle_specifics>;
    195 
    196 template <class _Iterator, class _NodeType>
    197 _LIBCPP_TEMPLATE_VIS
    198 struct __insert_return_type
    199 {
    200     _Iterator position;
    201     bool inserted;
    202     _NodeType node;
    203 };
    204 
    205 #endif // _LIBCPP_STD_VER > 14
    206 
    207 _LIBCPP_END_NAMESPACE_STD
    208 _LIBCPP_POP_MACROS
    209 
    210 #endif
    211