Explorar o código

feat(libstdc++): some more features of set

greatbridf hai 1 ano
pai
achega
feadee8506
Modificáronse 3 ficheiros con 150 adicións e 15 borrados
  1. 46 11
      gblibstdc++/include/bits/rbtree
  2. 82 4
      gblibstdc++/include/memory
  3. 22 0
      gblibstdc++/include/set

+ 46 - 11
gblibstdc++/include/bits/rbtree

@@ -239,25 +239,26 @@ struct rbtree {
 
     using node_allocator = typename
         std::allocator_traits<Allocator>::template rebind_alloc<node>;
+    using node_alloc_traits = std::allocator_traits<node_allocator>;
 
     node* root;
+    std::size_t _size;
     Compare comp;
     node_allocator alloc;
 
 private:
-    template <typename UKey>
-    constexpr node* newnode(UKey&& key)
+    template <typename... Args>
+    constexpr node* newnode(Args&&... key)
     {
-        node* ptr = std::allocator_traits<node_allocator>::allocate(alloc, 1);
-        std::allocator_traits<node_allocator>::construct(
-            alloc, ptr, std::forward<UKey>(key));
+        node* ptr = node_alloc_traits::allocate(alloc, 1);
+        node_alloc_traits::construct(alloc, ptr, std::forward<Args>(key)...);
         return ptr;
     }
 
     constexpr void delnode(node* nd)
     {
-        std::allocator_traits<node_allocator>::destroy(alloc, nd);
-        std::allocator_traits<node_allocator>::deallocate(alloc, nd, 1);
+        node_alloc_traits::destroy(alloc, nd);
+        node_alloc_traits::deallocate(alloc, nd, 1);
     }
 
 public:
@@ -284,7 +285,7 @@ public:
         delnode(nd);
     }
 
-    constexpr void destroy() { destroy(root); root = nullptr; }
+    constexpr void destroy() { destroy(root); root = nullptr; _size = 0; }
 
     constexpr node* copy(node* nd)
     {
@@ -293,6 +294,7 @@ public:
 
         node* newnd = newnode(nd->value);
         newnd->color = nd->color;
+        ++_size;
 
         newnd->left = copy(nd->left);
         if (newnd->left)
@@ -306,7 +308,7 @@ public:
     }
 
     explicit constexpr rbtree(const Compare& comp, const node_allocator& alloc)
-        : root(), comp(comp), alloc(alloc) {}
+        : root(), _size(), comp(comp), alloc(alloc) {}
 
     constexpr rbtree(const rbtree& other)
         : rbtree(other.comp, other.alloc)
@@ -326,10 +328,12 @@ public:
     
     constexpr rbtree(rbtree&& other) noexcept
         : root(std::exchange(other.root, nullptr))
+        , _size(std::exchange(other._size, 0))
         , comp(std::move(other.comp)), alloc(std::move(other.alloc)) {}
 
     constexpr rbtree(rbtree&& other, const node_allocator& alloc) noexcept
         : root(std::exchange(other.root, nullptr))
+        , _size(std::exchange(other._size, 0))
         , comp(std::move(other.comp)), alloc(alloc) {}
     
     constexpr ~rbtree() { destroy(); }
@@ -339,7 +343,8 @@ public:
         destroy(root);
 
         comp = other.comp;
-        alloc = other.alloc;
+        if constexpr (node_alloc_traits::propagate_on_copy_assignment::value)
+            alloc = other.alloc;
 
         root = copy(other.root);
         if (root)
@@ -350,8 +355,10 @@ public:
     {
         destroy(root);
         root = std::exchange(other.root, nullptr);
+        _size = std::exchange(other._size, 0);
         comp = std::move(other.comp);
-        alloc = std::move(other.alloc);
+        if constexpr (node_alloc_traits::propagate_on_move_assignment::value)
+            alloc = std::move(other.alloc);
     }
 
     constexpr void rotateleft(node* rt)
@@ -571,6 +578,7 @@ public:
     {
         node* nextpos = erase(pos.p);
         delnode(pos.p);
+        --_size;
         return iterator { nextpos };
     }
 
@@ -578,6 +586,7 @@ public:
     {
         node* nextpos = erase(pos.p);
         delnode(pos.p);
+        --_size;
         return const_iterator { nextpos };
     }
 
@@ -593,6 +602,7 @@ public:
                     nd->parent = cur;
                     cur->left = nd;
                     this->balance(nd);
+                    ++_size;
                     return;
                 } else {
                     cur = cur->left;
@@ -602,6 +612,7 @@ public:
                     nd->parent = cur;
                     cur->right = nd;
                     this->balance(nd);
+                    ++_size;
                     return;
                 } else {
                     cur = cur->right;
@@ -611,6 +622,7 @@ public:
 
         root = nd;
         root->toblack();
+        ++_size;
     }
 
     template <typename U>
@@ -626,7 +638,30 @@ public:
         return { iterator { ptr }, true };
     }
 
+    template <typename... Args>
+    constexpr std::pair<iterator, bool> emplace(Args&&... args)
+    {
+        node* nd = newnode(std::forward<Args>(args)...);
+        node* exist_nd = _find(nd->value);
+        if (exist_nd) {
+            delnode(nd);
+            return { iterator { exist_nd }, false };
+        }
+        insert(nd);
+        return { iterator { nd }, true };
+    }
+
     constexpr bool empty() const noexcept { return !root; }
+    constexpr std::size_t size() const noexcept { return _size; }
+
+    constexpr void swap(rbtree& other)
+    {
+        std::swap(root, other.root);
+        std::swap(_size, other._size);
+        std::swap(comp, other.comp);
+        if constexpr (node_alloc_traits::propagate_on_container_swap::value)
+            std::swap(alloc, other.alloc);
+    }
 };
 
 } // namespace std::impl

+ 82 - 4
gblibstdc++/include/memory

@@ -34,11 +34,79 @@ constexpr T* addressof(T& arg) noexcept
 template <typename T>
 const T* addressof(const T&&) = delete;
 
+namespace __helpers {
+
+template <typename Alloc, typename = void>
+struct allocator_pointer
+{ using type = std::add_pointer_t<typename Alloc::value_type>; };
+template <typename Alloc>
+struct allocator_pointer<Alloc,
+    std::void_t<typename Alloc::pointer>>
+{ using type = typename Alloc::pointer; };
+template <typename Alloc>
+using allocator_pointer_t =
+    typename allocator_pointer<Alloc>::type;
+
+template <typename Alloc, typename = void>
+struct allocator_difference_type
+{ using type = std::ptrdiff_t; };
+template <typename Alloc>
+struct allocator_difference_type<Alloc,
+    std::void_t<typename Alloc::difference_type>>
+{ using type = typename Alloc::difference_type; };
+template <typename Alloc>
+using allocator_difference_type_t =
+    typename allocator_difference_type<Alloc>::type;
+
+template <typename Alloc, typename = void>
+struct allocator_size_type
+{ using type = std::size_t; };
+template <typename Alloc>
+struct allocator_size_type<Alloc,
+    std::void_t<typename Alloc::size_type>>
+{ using type = typename Alloc::size_type; };
+template <typename Alloc>
+using allocator_size_type_t =
+    typename allocator_size_type<Alloc>::type;
+
+template <typename Alloc, typename = void>
+struct allocator_prop_copy
+{ using type = std::false_type; };
+template <typename Alloc>
+struct allocator_prop_copy<Alloc,
+    std::void_t<typename Alloc::propagate_on_container_copy_assignment>>
+{ using type = typename Alloc::propagate_on_container_copy_assignment; };
+template <typename Alloc>
+using allocator_prop_copy_t =
+    typename allocator_prop_copy<Alloc>::type;
+
+template <typename Alloc, typename = void>
+struct allocator_prop_move
+{ using type = std::false_type; };
+template <typename Alloc>
+struct allocator_prop_move<Alloc,
+    std::void_t<typename Alloc::propagate_on_container_move_assignment>>
+{ using type = typename Alloc::propagate_on_container_move_assignment; };
+template <typename Alloc>
+using allocator_prop_move_t =
+    typename allocator_prop_move<Alloc>::type;
+
+template <typename Alloc, typename = void>
+struct allocator_prop_swap
+{ using type = std::false_type; };
+template <typename Alloc>
+struct allocator_prop_swap<Alloc,
+    std::void_t<typename Alloc::propagate_on_container_swap>>
+{ using type = typename Alloc::propagate_on_container_swap; };
+template <typename Alloc>
+using allocator_prop_swap_t =
+    typename allocator_prop_swap<Alloc>::type;
+
+} // namespace __helpers
+
 template <typename T>
 struct allocator {
     using value_type = T;
-    using size_type = std::size_t;
-    using difference_type = std::ptrdiff_t;
 
     constexpr allocator() noexcept = default;
     constexpr allocator(const allocator& other) noexcept = default;
@@ -93,8 +161,18 @@ template <typename Allocator>
 struct allocator_traits {
     using allocator_type = Allocator;
     using value_type = typename Allocator::value_type;
-    using pointer = value_type*;
-    using size_type = std::size_t;
+    using pointer =
+        __helpers::allocator_pointer_t<Allocator>;
+    using difference_type =
+        __helpers::allocator_difference_type_t<Allocator>;
+    using size_type =
+        __helpers::allocator_size_type_t<Allocator>;
+    using propagate_on_container_copy_assignment =
+        __helpers::allocator_prop_copy_t<Allocator>;
+    using propagate_on_container_move_assignment =
+        __helpers::allocator_prop_move_t<Allocator>;
+    using propagate_on_container_swap =
+        __helpers::allocator_prop_swap_t<Allocator>;
 
     template <typename T>
     using rebind_alloc = typename __helpers::rebind<Allocator, T>::type;

+ 22 - 0
gblibstdc++/include/set

@@ -121,6 +121,10 @@ public:
             insert(*first);
     }
 
+    template <typename... Args>
+    std::pair<iterator, bool> emplace(Args&&... args)
+    { return tree.emplace(std::forward<Args>(args)...); }
+
     __GBLIBCPP_CONSTEXPR
     iterator erase(iterator pos) noexcept { return tree.erase(pos); }
     __GBLIBCPP_CONSTEXPR
@@ -148,8 +152,26 @@ public:
 
     __GBLIBCPP_CONSTEXPR
     bool empty() const noexcept { return tree.empty(); }
+
+    __GBLIBCPP_CONSTEXPR
+    size_type size() const noexcept { return tree.size(); }
+
+    __GBLIBCPP_CONSTEXPR
+    void swap(set& other) { tree.swap(other.tree); }
+
+    __GBLIBCPP_CONSTEXPR
+    size_type count(const Key& key) const
+    { return find(key) ? 1 : 0; }
+
+    __GBLIBCPP_CONSTEXPR
+    bool contains(const Key& key) const { return count(key) != 0; }
 };
 
+template <typename Key, typename Compare, typename Allocator>
+void swap(std::set<Key, Compare, Allocator>& lhs,
+    std::set<Key, Compare, Allocator>& rhs)
+{ lhs.swap(rhs); }
+
 } // namespace std
 
 #endif