Bläddra i källkod

change(gblibstdc++): use EBO for all stl classes

greatbridf 8 månader sedan
förälder
incheckning
f88b4da3fd

+ 71 - 62
gblibstdc++/include/bits/rbtree

@@ -1,6 +1,8 @@
 #ifndef __GBLIBCPP_BITS_RBTREE__
 #define __GBLIBCPP_BITS_RBTREE__
 
+#include "compressed_pair"
+
 #include <cstddef>
 #include <functional>
 #include <utility>
@@ -250,24 +252,34 @@ struct rbtree {
         std::allocator_traits<Allocator>::template rebind_alloc<node>;
     using node_alloc_traits = std::allocator_traits<node_allocator>;
 
-    node* root;
-    node_allocator alloc;
-    std::size_t _size;
-    Compare comp;
+    compressed_pair<node*, node_allocator> root_data;
+    compressed_pair<std::size_t, Compare> size_data;
 
 private:
+    constexpr node*& _root() noexcept { return root_data.first(); }
+    constexpr node* const& _root() const noexcept { return root_data.first(); }
+
+    constexpr std::size_t& _size() noexcept { return size_data.first(); }
+    constexpr const std::size_t& _size() const noexcept { return size_data.first(); }
+
+    constexpr node_allocator& _alloc() noexcept { return root_data.second(); }
+    constexpr const node_allocator& _alloc() const noexcept { return root_data.second(); }
+
+    constexpr Compare& _comp() noexcept { return size_data.second(); }
+    constexpr const Compare& _comp() const noexcept { return size_data.second(); }
+
     template <typename... Args>
     constexpr node* newnode(Args&&... key)
     {
-        node* ptr = node_alloc_traits::allocate(alloc, 1);
-        node_alloc_traits::construct(alloc, ptr, std::forward<Args>(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)
     {
-        node_alloc_traits::destroy(alloc, nd);
-        node_alloc_traits::deallocate(alloc, nd, 1);
+        node_alloc_traits::destroy(_alloc(), nd);
+        node_alloc_traits::deallocate(_alloc(), nd, 1);
     }
 
     constexpr void do_insertion(node* parent,
@@ -276,7 +288,7 @@ private:
         nd->parent = parent;
         child_inserted = nd;
         this->balance(nd);
-        ++_size;
+        ++_size();
     }
 
 public:
@@ -288,11 +300,11 @@ public:
     { return const_iterator(nullptr); }
 
     constexpr iterator begin(void) noexcept
-    { return root ? iterator(root->leftmost()) : end(); }
+    { return _root() ? iterator(_root()->leftmost()) : end(); }
     constexpr const_iterator begin(void) const noexcept
-    { return root ? const_iterator(root->leftmost()) : end(); }
+    { return _root() ? const_iterator(_root()->leftmost()) : end(); }
     constexpr const_iterator cbegin(void) const noexcept
-    { return root ? const_iterator(root->leftmost()) : end(); }
+    { return _root() ? const_iterator(_root()->leftmost()) : end(); }
 
     constexpr void destroy(node* nd)
     {
@@ -303,7 +315,7 @@ public:
         delnode(nd);
     }
 
-    constexpr void destroy() { destroy(root); root = nullptr; _size = 0; }
+    constexpr void destroy() { destroy(_root()); _root() = nullptr; _size() = 0; }
 
     constexpr node* copy(node* nd)
     {
@@ -312,7 +324,7 @@ public:
 
         node* newnd = newnode(nd->value);
         newnd->color = nd->color;
-        ++_size;
+        ++_size();
 
         newnd->left = copy(nd->left);
         if (newnd->left)
@@ -326,62 +338,59 @@ public:
     }
 
     explicit constexpr rbtree(const Compare& comp, const node_allocator& alloc)
-        : root(), alloc(alloc), _size(), comp(comp) {}
+        : root_data{nullptr, alloc}, size_data{0, comp} { }
 
     constexpr rbtree(const rbtree& other)
-        : rbtree(other.comp, other.alloc)
+        : rbtree(other._comp(), other._alloc())
     {
-        root = copy(other.root);
-        if (root)
-            root->parent = nullptr;
+        _root() = copy(other._root());
+        if (_root())
+            _root()->parent = nullptr;
     }
 
     constexpr rbtree(const rbtree& other, const node_allocator& alloc)
-        : rbtree(other.comp, alloc)
+        : rbtree(other._comp(), alloc)
     {
-        root = copy(other.root);
-        if (root)
-            root->parent = nullptr;
+        _root() = copy(other._root());
+        if (_root())
+            _root()->parent = nullptr;
     }
 
     constexpr rbtree(rbtree&& other) noexcept
-        : root(std::exchange(other.root, nullptr))
-        , alloc(std::move(other.alloc))
-        , _size(std::exchange(other._size, 0))
-        , comp(std::move(other.comp)) {}
+        : root_data{std::exchange(other._root(), nullptr), std::move(other._alloc())}
+        , size_data{std::exchange(other._size(), 0), std::move(other._comp())} { }
 
     constexpr rbtree(rbtree&& other, const node_allocator& alloc) noexcept
-        : root(std::exchange(other.root, nullptr))
-        , alloc(alloc) , _size(std::exchange(other._size, 0))
-        , comp(std::move(other.comp)) {}
+        : root_data{std::exchange(other._root(), nullptr), alloc}
+        , size_data{std::exchange(other._size(), 0), std::move(other._comp())} { }
 
     constexpr ~rbtree() { destroy(); }
 
     constexpr rbtree& operator=(const rbtree& other)
     {
-        destroy(root);
+        destroy(_root());
 
-        comp = other.comp;
+        _comp() = other._comp();
         if constexpr (node_alloc_traits::
             propagate_on_container_copy_assignment::value)
-            alloc = other.alloc;
+            _alloc() = other._alloc();
 
-        root = copy(other.root);
-        if (root)
-            root->parent = nullptr;
+        _root() = copy(other._root());
+        if (_root())
+            _root()->parent = nullptr;
 
         return *this;
     }
 
     constexpr rbtree& operator=(rbtree&& other) noexcept
     {
-        destroy(root);
-        root = std::exchange(other.root, nullptr);
-        _size = std::exchange(other._size, 0);
-        comp = std::move(other.comp);
+        destroy(_root());
+        _root() = std::exchange(other._root(), nullptr);
+        _size() = std::exchange(other._size(), 0);
+        _comp() = std::move(other._comp());
         if constexpr (node_alloc_traits::
             propagate_on_container_move_assignment::value)
-            alloc = std::move(other.alloc);
+            _alloc() = std::move(other._alloc());
 
         return *this;
     }
@@ -396,7 +405,7 @@ public:
             else
                 rt->parent->right = nrt;
         } else {
-            this->root = nrt;
+            _root() = nrt;
         }
 
         nrt->parent = rt->parent;
@@ -419,7 +428,7 @@ public:
             else
                 rt->parent->right = nrt;
         } else {
-            this->root = nrt;
+            _root() = nrt;
         }
 
         nrt->parent = rt->parent;
@@ -477,10 +486,10 @@ public:
     template <typename U>
     constexpr node* _find(const U& key) const
     {
-        for (node* cur = root; cur; ) {
-            if (comp(key, cur->value))
+        for (node* cur = _root(); cur; ) {
+            if (_comp()(key, cur->value))
                 cur = cur->left;
-            else if (comp(cur->value, key))
+            else if (_comp()(cur->value, key))
                 cur = cur->right;
             else
                 return cur;
@@ -565,7 +574,7 @@ public:
     constexpr node* erase(node* nd)
     {
         if (nd->is_root() && nd->is_leaf()) {
-            root = nullptr;
+            _root() = nullptr;
             return nullptr;
         }
 
@@ -574,7 +583,7 @@ public:
         while (!nd->is_leaf()) {
             node* alt = nd->right ? nd->right->leftmost() : nd->left;
             if (nd->is_root())
-                this->root = alt;
+                _root() = alt;
             node::swap(nd, alt);
         }
 
@@ -592,7 +601,7 @@ public:
     {
         node* nextpos = erase(pos.p);
         delnode(pos.p);
-        --_size;
+        --_size();
         return iterator { nextpos };
     }
 
@@ -600,18 +609,18 @@ public:
     {
         node* nextpos = erase(pos.p);
         delnode(pos.p);
-        --_size;
+        --_size();
         return iterator { nextpos };
     }
 
     template <typename U>
     constexpr iterator lower_bound(U&& val) const
     {
-        node* cur = root;
+        node* cur = _root();
         node* result = nullptr;
 
         while (cur) {
-            if (!comp(cur->value, val)) {
+            if (!_comp()(cur->value, val)) {
                 result = cur;
                 cur = cur->left;
             }
@@ -627,7 +636,7 @@ public:
     constexpr iterator upper_bound(U&& val) const
     {
         iterator iter = lower_bound(std::forward<U>(val));
-        if (iter && !comp(*iter, val) && !comp(val, *iter))
+        if (iter && !_comp()(*iter, val) && !_comp()(val, *iter))
             return ++iter;
         return iter;
     }
@@ -636,10 +645,10 @@ public:
     // that is, if a < b, then a > b
     constexpr void insert(node* nd)
     {
-        node* cur = root;
+        node* cur = _root();
 
         while (cur) {
-            if (comp(nd->value, cur->value)) {
+            if (_comp()(nd->value, cur->value)) {
                 if (!cur->left) {
                     do_insertion(cur, cur->left, nd);
                     return;
@@ -653,7 +662,7 @@ public:
                 cur = cur->right;
             }
         }
-        do_insertion(cur, root, nd);
+        do_insertion(cur, _root(), nd);
     }
 
     template <typename U>
@@ -682,16 +691,16 @@ public:
         return { iterator { nd }, true };
     }
 
-    constexpr bool empty() const noexcept { return !root; }
-    constexpr std::size_t size() const noexcept { return _size; }
+    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);
+        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);
+            std::swap(_alloc(), other._alloc());
     }
 };
 

+ 1 - 1
gblibstdc++/include/functional

@@ -38,7 +38,7 @@ class reference_wrapper {
 private:
     T* _ptr;
 
-    template <typename Ref, typename = 
+    template <typename Ref, typename =
         decltype(__helpers::__reference_wrapper_check<T>(std::declval<Ref>()))>
     struct __check_reference_valid
         : public bool_constant<!std::is_same_v<reference_wrapper, std::decay_t<Ref>>> {};

+ 41 - 48
gblibstdc++/include/list

@@ -1,6 +1,7 @@
 #ifndef __GBLIBCPP_LIST__
 #define __GBLIBCPP_LIST__
 
+#include <bits/compressed_pair>
 #include <bits/iter_ops>
 
 #include <memory>
@@ -11,8 +12,7 @@
 
 namespace std {
 
-template <typename T,
-    typename Allocator = std::allocator<T>>
+template <typename T, typename Allocator = std::allocator<T>>
 class list {
 private:
     struct node_base {
@@ -75,7 +75,7 @@ public:
         using reference = std::add_lvalue_reference_t<value_type>;
 
         friend class list;
-    
+
     private:
         node_pointer p;
 
@@ -110,20 +110,25 @@ public:
 
 private:
     node_base m_head;
-    size_type m_size;
-    node_alloc_type m_alloc;
+    impl::compressed_pair<size_type, node_alloc_type> m_pair;
 
 private:
     // move m_head and m_size of other to *this
     // other MUST NOT be empty, *this MUST be empty
     constexpr void _move_from(list&& other) noexcept
     {
-        std::swap(m_size, other.m_size);
+        std::swap(_size(), other._size());
         other.m_head.prev->connect(&m_head);
         m_head.connect(other.m_head.next);
         other.m_head.next = other.m_head.prev = &other.m_head;
     }
 
+    constexpr size_type& _size() noexcept { return m_pair.first(); }
+    constexpr const size_type& _size() const noexcept { return m_pair.first(); }
+
+    constexpr node_alloc_type& _alloc() noexcept { return m_pair.second(); }
+    constexpr const node_alloc_type& _alloc() const noexcept { return m_pair.second(); }
+
 public:
     __GBLIBCPP_CONSTEXPR
     iterator end(void) noexcept { return iterator { &m_head }; }
@@ -144,38 +149,33 @@ public:
     __GBLIBCPP_CONSTEXPR
     iterator emplace(const_iterator pos, Args&&... args)
     {
-        node* nd = node_alloc_traits::allocate(m_alloc, 1);
-        node_alloc_traits::construct(m_alloc, nd, std::forward<Args>(args)...);
+        node* nd = node_alloc_traits::allocate(_alloc(), 1);
+        node_alloc_traits::construct(_alloc(), nd, std::forward<Args>(args)...);
 
         nd->next = pos.p;
         nd->prev = pos.p->prev;
         nd->next->prev = nd;
         nd->prev->next = nd;
 
-        ++m_size;
+        ++_size();
         return iterator { nd };
     }
-    
+
     explicit __GBLIBCPP_CONSTEXPR
-    list(const Allocator& alloc)
-        : m_head { }, m_size { }, m_alloc(alloc) { }
+    list(const Allocator& alloc): m_head{}, m_pair{0, alloc} { }
 
     __GBLIBCPP_CONSTEXPR
-    list() : list(Allocator()) {}
+    list(): list(Allocator()) {}
 
     __GBLIBCPP_CONSTEXPR
-    explicit list(size_type count,
-        const Allocator& alloc = Allocator())
-        : list(alloc)
+    explicit list(size_type count, const Allocator& alloc = Allocator()): list(alloc)
     {
         while (count--)
             emplace_back();
     }
 
     __GBLIBCPP_CONSTEXPR
-    list(size_type count, const T& value,
-        const Allocator& alloc = Allocator())
-        : list(alloc)
+    list(size_type count, const T& value, const Allocator& alloc = Allocator()): list(alloc)
     {
         while (count--)
             emplace_back(value);
@@ -183,28 +183,22 @@ public:
 
     template <typename InputIter>
     __GBLIBCPP_CONSTEXPR
-    list(InputIter first, InputIter last,
-        const Allocator& alloc = Allocator())
+    list(InputIter first, InputIter last, const Allocator& alloc = Allocator())
         : list(alloc) { insert(first, last); }
 
     __GBLIBCPP_CONSTEXPR
-    list(const list& other, const Allocator& alloc)
-        : list(alloc)
+    list(const list& other, const Allocator& alloc): list(alloc)
     {
         // TODO: select_on_container_copy_construction
         for (const auto& item : other)
             emplace_back(item);
     }
     __GBLIBCPP_CONSTEXPR
-    list(const list& other)
-        : list(other,
-            alloc_traits::select_on_container_copy_construction(m_alloc))
-    { }
+    list(const list& other): list(other,
+            alloc_traits::select_on_container_copy_construction(_alloc())) { }
 
     __GBLIBCPP_CONSTEXPR
-    list(list&& other)
-        : m_head { }, m_size { }
-        , m_alloc(std::move(other.m_alloc))
+    list(list&& other): m_head{}, m_pair{0, std::move(other._alloc())}
     {
         if (other.empty())
             return;
@@ -212,16 +206,15 @@ public:
     }
 
     __GBLIBCPP_CONSTEXPR
-    list(list&& other, const Allocator& alloc)
-        : m_head { }, m_size { }, m_alloc(alloc)
+    list(list&& other, const Allocator& alloc): m_head{}, m_pair{0, alloc}
     {
-        if (other.m_alloc != alloc) {
+        if (other._alloc() != alloc) {
             for (auto iter = other.begin(); iter != other.end(); ++iter)
                 emplace(cend(), std::move(*iter));
             other.clear();
             return;
         }
-        // other.m_alloc == alloc
+        // other._alloc() == alloc
         if (other.empty())
             return;
 
@@ -236,23 +229,23 @@ public:
         for (const auto& item : ilist)
             emplace_back(item);
     }
-    
+
     __GBLIBCPP_CONSTEXPR
     ~list()
     {
         clear();
         m_head.next = m_head.prev = nullptr;
     }
-    
+
     __GBLIBCPP_CONSTEXPR
     list& operator=(const list& other)
     {
-        // TODO: reuse memory if m_alloc == other.m_alloc
+        // TODO: reuse memory if _alloc() == other._alloc()
         clear();
 
         if constexpr (alloc_traits::
             propagate_on_container_copy_assignment::value)
-            m_alloc = other.m_alloc;
+            _alloc() = other._alloc();
 
         for (const auto& item : other)
             emplace_back(item);
@@ -265,7 +258,7 @@ public:
         if (alloc_traits::
             propagate_on_container_move_assignment::value) {
             clear();
-            m_alloc = std::move(other.m_alloc);
+            _alloc() = std::move(other._alloc());
 
             if (other.empty())
                 return *this;
@@ -274,10 +267,10 @@ public:
             return *this;
         }
 
-        // TODO: reuse memory if m_alloc == other.m_alloc
+        // TODO: reuse memory if _alloc() == other._alloc()
         clear();
 
-        if (m_alloc != other.m_alloc) {
+        if (_alloc() != other._alloc()) {
             for (auto iter = other.begin(); iter != other.end(); ++iter)
                 emplace(cend(), std::move(*iter));
             other.clear();
@@ -323,7 +316,7 @@ public:
     }
 
     __GBLIBCPP_CONSTEXPR
-    allocator_type get_allocator() const noexcept { return m_alloc; }
+    allocator_type get_allocator() const noexcept { return _alloc(); }
 
     __GBLIBCPP_CONSTEXPR
     reference front() { return *begin(); }
@@ -398,10 +391,10 @@ public:
         pos.p->next->prev = pos.p->prev;
         pos.p->prev->next = pos.p->next;
 
-        node_alloc_traits::destroy(m_alloc, (node*)pos.p);
-        node_alloc_traits::deallocate(m_alloc, (node*)pos.p, 1);
+        node_alloc_traits::destroy(_alloc(), (node*)pos.p);
+        node_alloc_traits::deallocate(_alloc(), (node*)pos.p, 1);
 
-        --m_size;
+        --_size();
         return ret;
     }
 
@@ -421,7 +414,7 @@ public:
     }
 
     __GBLIBCPP_CONSTEXPR
-    size_type size() const noexcept { return m_size; }
+    size_type size() const noexcept { return _size(); }
 
     __GBLIBCPP_CONSTEXPR
     bool empty() const noexcept { return size() == 0; }
@@ -430,9 +423,9 @@ public:
     void swap(list& other)
     {
         if constexpr (alloc_traits::propagate_on_container_swap::value)
-            std::swap(m_alloc, other.m_alloc);
+            std::swap(_alloc(), other._alloc());
 
-        std::swap(m_size, other.m_size);
+        std::swap(_size(), other.m_size);
         std::swap(m_head, other.m_head);
         std::swap(m_head.next->prev, other.m_head.next->prev);
         std::swap(m_head.prev->next, other.m_head.prev->next);

+ 9 - 10
gblibstdc++/include/map

@@ -26,25 +26,24 @@ public:
     using allocator_type = Allocator;
 
 private:
-    class value_compare {
+    class value_compare : public Compare {
     protected:
-        Compare comp;
-        constexpr value_compare(Compare c) : comp(c) {}
+        constexpr value_compare(Compare c): Compare{c} {}
 
         friend class map;
 
     public:
         constexpr bool operator()(
             const value_type& lhs, const value_type& rhs) const
-        { return comp(lhs.first, rhs.first); }
+        { return Compare::operator()(lhs.first, rhs.first); }
 
         constexpr bool operator()(
             const Key& lhs, const value_type& rhs) const
-        { return comp(lhs, rhs.first); }
+        { return Compare::operator()(lhs, rhs.first); }
 
         constexpr bool operator()(
             const value_type& lhs, const Key& rhs) const
-        { return comp(lhs.first, rhs); }
+        { return Compare::operator()(lhs.first, rhs); }
     };
 
     using rbtree_type = impl::rbtree<value_type, value_compare, Allocator>;
@@ -76,7 +75,7 @@ public:
     map(const Compare& comp,
         const Allocator& alloc = Allocator())
         : tree(comp, alloc) {}
-    
+
     explicit __GBLIBCPP_CONSTEXPR
     map(const Allocator& alloc)
         : map(Compare(), alloc) {}
@@ -111,7 +110,7 @@ public:
     __GBLIBCPP_CONSTEXPR
     map(map&& other, const Allocator& alloc)
         : tree(std::move(other.tree), alloc) {}
-    
+
     __GBLIBCPP_CONSTEXPR
     map(std::initializer_list<value_type> init,
         const Compare& comp = Compare(),
@@ -123,10 +122,10 @@ public:
     map(std::initializer_list<value_type> init,
         const Allocator& alloc)
         : map(init, Compare(), alloc) {}
-    
+
     __GBLIBCPP_CONSTEXPR
     ~map() { clear(); }
-    
+
     __GBLIBCPP_CONSTEXPR
     map& operator=(const map& other) = default;
     __GBLIBCPP_CONSTEXPR

+ 24 - 37
gblibstdc++/include/memory

@@ -362,6 +362,19 @@ struct allocator_traits {
     { return __helpers::allocator_select_on_copy<Allocator>::get(alloc); }
 };
 
+template <typename T>
+struct default_delete {
+    __GBLIBCPP_CONSTEXPR default_delete() noexcept = default;
+
+    template <typename U, std::enable_if_t<std::is_convertible_v<U*, T*>, bool> = true>
+    __GBLIBCPP_CONSTEXPR default_delete(const default_delete<U>&) noexcept {}
+
+    __GBLIBCPP_CONSTEXPR void operator()(T* p) const
+    {
+        delete p;
+    }
+};
+
 // TODO: weak_ptr
 template <typename T>
 class shared_ptr {
@@ -397,40 +410,27 @@ private:
     };
 
     template <typename Deleter>
-    struct control_block : public virtual control_block_base {
-        Deleter deleter;
+    struct control_block : public virtual control_block_base, private Deleter {
+        using Base = control_block_base;
+
         virtual constexpr ~control_block() = default;
 
+        constexpr control_block(std::size_t ref_count, std::size_t weak_count, pointer ptr)
+            : control_block_base { ref_count, weak_count, ptr }, Deleter{} { }
+
         template <typename UDeleter>
         constexpr control_block(std::size_t ref_count,
             std::size_t weak_count, pointer ptr, UDeleter&& deleter)
             : control_block_base { ref_count, weak_count, ptr }
-            , deleter(std::forward<UDeleter>(deleter))
+            , Deleter(std::forward<UDeleter>(deleter))
         {
         }
 
         virtual constexpr void do_delete() override
         {
-            if (this->ptr)
-                deleter(this->ptr);
-            this->ptr = nullptr;
-        }
-    };
-
-    struct default_control_block : public virtual control_block_base {
-        virtual constexpr ~default_control_block() = default;
-
-        constexpr default_control_block(std::size_t ref_count,
-            std::size_t weak_count, pointer ptr)
-            : control_block_base { ref_count, weak_count, ptr }
-        {
-        }
-
-        virtual constexpr void do_delete() override
-        {
-            if (this->ptr)
-                delete this->ptr;
-            this->ptr = nullptr;
+            if (this->Base::ptr)
+                this->Deleter::operator()(this->Base::ptr);
+            this->Base::ptr = nullptr;
         }
     };
 
@@ -465,7 +465,7 @@ public:
 
     template <typename U, enable_if_t<is_convertible_v<U*, T*>, bool> = true>
     __GBLIBCPP_CONSTEXPR explicit shared_ptr(U* p) // TODO: array type
-        : cb(new default_control_block { 1, 0, p })
+        : cb(new control_block<default_delete<T>> { 1, 0, p })
         , ptr(p)
     {
     }
@@ -637,19 +637,6 @@ public:
     }
 };
 
-template <typename T>
-struct default_delete {
-    __GBLIBCPP_CONSTEXPR default_delete() noexcept = default;
-
-    template <typename U, std::enable_if_t<std::is_convertible_v<U*, T*>, bool> = true>
-    __GBLIBCPP_CONSTEXPR default_delete(const default_delete<U>&) noexcept {}
-
-    __GBLIBCPP_CONSTEXPR void operator()(T* p) const
-    {
-        delete p;
-    }
-};
-
 template <typename T, typename Deleter = std::default_delete<T>>
 class unique_ptr {
 public:

+ 1 - 1
gblibstdc++/include/queue

@@ -48,7 +48,7 @@ public:
     __GBLIBCPP_CONSTEXPR
     explicit priority_queue(const Compare& comp)
         : priority_queue(comp, Container()) {}
-    
+
     template <typename InputIter>
     __GBLIBCPP_CONSTEXPR
     priority_queue(InputIter first, InputIter last,

+ 34 - 31
gblibstdc++/include/string

@@ -1,6 +1,7 @@
 #ifndef __GBLIBCPP_STRING__
 #define __GBLIBCPP_STRING__
 
+#include <bits/compressed_pair>
 #include <bits/iter_ops>
 
 #include <algorithm>
@@ -106,7 +107,7 @@ private:
     static constexpr std::size_t STATIC_COUNT =
         STATIC_SIZE / sizeof(Char) - 2;
 
-    union {
+    struct string_data_type { union {
         std::byte __data[STATIC_SIZE];
 
         struct {
@@ -124,17 +125,20 @@ private:
             Char* m_ptr;
         } heapdata;
 
-    } m_data;
-    Allocator m_alloc;
+    } in; };
+    impl::compressed_pair<string_data_type, Allocator> m_data;
+
+    constexpr Allocator& _alloc() noexcept { return m_data.second(); }
+    constexpr const Allocator& _alloc() const noexcept { return m_data.second(); }
 
     constexpr bool _stack_data() const
     {
-        return m_data.stackdata.end == 0;
+        return m_data.first().in.stackdata.end == 0;
     }
 
     constexpr bool _stack_data(bool val)
     {
-        return (m_data.stackdata.end = !val), val;
+        return (m_data.first().in.stackdata.end = !val), val;
     }
 
     constexpr void _release()
@@ -144,7 +148,7 @@ private:
             return;
         }
 
-        alloc_traits::deallocate(m_alloc, data(), capacity()+1);
+        alloc_traits::deallocate(m_data.second(), data(), capacity()+1);
 
         _stack_data(true);
         _size(0);
@@ -154,7 +158,7 @@ private:
     constexpr void _reserve(std::size_t cnt)
     {
         std::size_t cursize = size();
-        Char* newdata = alloc_traits::allocate(m_alloc, cnt+1);
+        Char* newdata = alloc_traits::allocate(_alloc(), cnt+1);
 
         memcpy(newdata, data(), size());
         newdata[cursize] = 0;
@@ -164,7 +168,7 @@ private:
             _size(cursize);
         }
         else {
-            alloc_traits::deallocate(m_alloc, data(), capacity()+1);
+            alloc_traits::deallocate(_alloc(), data(), capacity()+1);
         }
 
         _capacity(cnt);
@@ -174,17 +178,17 @@ private:
     constexpr std::size_t _size() const
     {
         if (_stack_data())
-            return m_data.stackdata.m_size.n;
+            return m_data.first().in.stackdata.m_size.n;
         else
-            return m_data.heapdata.m_size;
+            return m_data.first().in.heapdata.m_size;
     }
 
     constexpr std::size_t _size(std::size_t val)
     {
         if (_stack_data())
-            return m_data.stackdata.m_size.n = (Char)val;
+            return m_data.first().in.stackdata.m_size.n = (Char)val;
         else
-            return m_data.heapdata.m_size = val;
+            return m_data.first().in.heapdata.m_size = val;
     }
 
     constexpr std::size_t _capacity() const
@@ -192,7 +196,7 @@ private:
         if (_stack_data())
             return STATIC_COUNT;
         else
-            return m_data.heapdata.m_capacity;
+            return m_data.first().in.heapdata.m_capacity;
     }
 
     constexpr std::size_t _capacity(std::size_t val)
@@ -200,31 +204,31 @@ private:
         if (_stack_data())
             return STATIC_COUNT;
         else
-            return m_data.heapdata.m_capacity = val;
+            return m_data.first().in.heapdata.m_capacity = val;
     }
 
     constexpr const Char* _data() const
     {
         if (_stack_data())
-            return m_data.stackdata.str;
+            return m_data.first().in.stackdata.str;
         else
-            return m_data.heapdata.m_ptr;
+            return m_data.first().in.heapdata.m_ptr;
     }
 
     constexpr Char* _data()
     {
         if (_stack_data())
-            return m_data.stackdata.str;
+            return m_data.first().in.stackdata.str;
         else
-            return m_data.heapdata.m_ptr;
+            return m_data.first().in.heapdata.m_ptr;
     }
 
     constexpr Char* _data(Char* val)
     {
         if (_stack_data())
-            return m_data.stackdata.str;
+            return m_data.first().in.stackdata.str;
         else
-            return m_data.heapdata.m_ptr = val;
+            return m_data.first().in.heapdata.m_ptr = val;
     }
 
 public:
@@ -232,7 +236,7 @@ public:
         : basic_string{Allocator{}} { }
 
     constexpr explicit basic_string(const Allocator& alloc) noexcept
-        : m_data{}, m_alloc{alloc} { }
+        : m_data{{}, alloc} { }
 
     constexpr basic_string(const basic_string& other, const Allocator& alloc)
         : basic_string{alloc}
@@ -242,12 +246,11 @@ public:
 
     constexpr basic_string(const basic_string& other)
         : basic_string{other, alloc_traits::
-            select_on_container_copy_construction(other.m_alloc)} { }
+            select_on_container_copy_construction(other._alloc())} { }
 
     constexpr basic_string(basic_string&& other) noexcept
-        : m_alloc{std::move(other.m_alloc)}
+        : m_data{other.m_data.first(), std::move(other._alloc())}
     {
-        memcpy(&m_data, &other.m_data, sizeof(m_data));
         other._stack_data(true);
         other._size(0);
         other._data()[0] = 0;
@@ -256,8 +259,8 @@ public:
     constexpr basic_string(basic_string&& other, const Allocator& alloc)
         : basic_string{alloc}
     {
-        if (alloc == other.m_alloc) {
-            memcpy(&m_data, &other.m_data, sizeof(m_data));
+        if (alloc == other._alloc()) {
+            m_data.first() = other.m_data.first();
             other._stack_data(true);
             other._size(0);
             other._data()[0] = 0;
@@ -308,17 +311,17 @@ public:
         if constexpr (alloc_traits::
                 propagate_on_container_move_assignment::value) {
             _release();
-            m_alloc = std::move(other.m_alloc);
+            _alloc() = std::move(other._alloc());
         }
         else {
-            if (m_alloc != other.m_alloc) {
+            if (_alloc() != other._alloc()) {
                 assign(other.c_str(), other.size());
                 return *this;
             }
             _release();
         }
 
-        memcpy(&m_data, &other.m_data, sizeof(m_data));
+        m_data.first() = other.m_data.first();
         other._stack_data(true);
         other._size(0);
         other._data()[0] = 0;
@@ -487,8 +490,8 @@ public:
         || alloc_traits::is_always_equal::value)
     {
         if (alloc_traits::propagate_on_container_swap::value)
-            std::swap(m_alloc, other.m_alloc);
-        std::swap(m_data, other.m_data);
+            std::swap(_alloc(), other._alloc());
+        std::swap(m_data.first(), other.m_data.first());
     }
 
     constexpr int compare(const basic_string& str) const noexcept

+ 9 - 9
gblibstdc++/include/tuple

@@ -80,7 +80,7 @@ class tuple_impl<0> {
     template <std::size_t> constexpr void _getr(void) const = delete;
 public:
     constexpr tuple_impl() noexcept = default;
-    
+
     constexpr tuple_impl(const tuple_impl& arg) noexcept = default;
     constexpr tuple_impl(tuple_impl&& arg) noexcept = default;
 
@@ -88,7 +88,7 @@ public:
     constexpr tuple_impl(const std::tuple<UTypes...>& other) = delete;
     template <typename... UTypes>
     constexpr tuple_impl(std::tuple<UTypes...>&& other) = delete;
-    
+
     constexpr tuple_impl& operator=(const tuple_impl& other) noexcept = default;
     constexpr tuple_impl& operator=(tuple_impl&& other) noexcept = default;
 };
@@ -157,13 +157,13 @@ class tuple_impl<I, Type, Types...> {
 public:
     constexpr tuple_impl()
         : val(), next() {}
-    
+
     constexpr tuple_impl(const tuple_impl& arg) = default;
     constexpr tuple_impl(tuple_impl&& arg) = default;
 
     constexpr tuple_impl(const Type& val, const Types&... vals)
         : val(val), next(vals...) {}
-    
+
     template <typename UType, typename... UTypes>
     constexpr tuple_impl(UType&& val, UTypes&&... vals)
         : val(std::forward<UType>(val)), next(std::forward<UTypes>(vals)...) {}
@@ -174,7 +174,7 @@ public:
     template <typename... UTypes>
     constexpr tuple_impl(std::tuple<UTypes...>&& other)
         : val(std::get<I>(other)), next(std::move(other)) {}
-    
+
     constexpr tuple_impl& operator=(const tuple_impl& other) = default;
     constexpr tuple_impl& operator=(tuple_impl&& other) = default;
 };
@@ -227,7 +227,7 @@ class tuple_impl<I, Type> {
 public:
     constexpr tuple_impl()
         : val() {}
-    
+
     constexpr tuple_impl(const tuple_impl& arg) = default;
     constexpr tuple_impl(tuple_impl&& arg) = default;
 
@@ -329,7 +329,7 @@ public:
     , bool> = true>
     constexpr tuple(const Types&... args)
         : base(args...) {}
-    
+
     template <typename... UTypes, std::enable_if_t<
         sizeof...(UTypes) == sizeof...(Types)
         && sizeof...(Types) >= 1
@@ -353,14 +353,14 @@ public:
     , bool> = true>
     constexpr tuple(tuple<UTypes...>&& other)
         : base(std::move(other)) {}
-    
+
     template <typename U1, typename U2, std::enable_if_t<
         __helpers::tuple_constraints<Types...>::template
             tuple_pair_constructible<const std::pair<U1, U2>&>::value
     , bool> = true>
     constexpr tuple(const std::pair<U1, U2>& p)
         : base(std::get<0>(p), std::get<1>(p)) {}
-    
+
     template <typename U1, typename U2, std::enable_if_t<
         __helpers::tuple_constraints<Types...>::template
             tuple_pair_constructible<std::pair<U1, U2>&&>::value

+ 1 - 1
gblibstdc++/include/utility

@@ -126,7 +126,7 @@ struct pair {
         second = std::forward<U2>(other.second);
         return *this;
     }
-    
+
     constexpr void swap(pair& other)
     {
         std::swap(first, other.first);

+ 64 - 60
gblibstdc++/include/vector

@@ -2,6 +2,7 @@
 #define __GBLIBCPP_VECTOR__
 
 #include <bits/iter_ops>
+#include <bits/compressed_pair>
 
 #include <functional>
 #include <memory>
@@ -84,27 +85,31 @@ public:
     using const_iterator = _iterator<true>;
 
 private:
-    T* m_data;
+    impl::compressed_pair<T*, allocator_type> m_data;
     size_type m_size;
     size_type m_capacity;
-    allocator_type m_alloc;
 
 private:
+    constexpr allocator_type& _alloc() noexcept { return m_data.second(); }
+    constexpr const allocator_type& _alloc() const noexcept { return m_data.second(); }
+    constexpr T*& _data() noexcept { return m_data.first(); }
+    constexpr T* const& _data() const noexcept { return m_data.first(); }
+
     // assert(n >= m_size)
     constexpr void _reallocate_safe(size_type n)
     {
         T* newptr = nullptr;
         if (n)
-            newptr = alloc_traits::allocate(m_alloc, n);
+            newptr = alloc_traits::allocate(_alloc(), n);
 
         for (size_t i = 0; i < m_size; ++i) {
             if (n)
-                alloc_traits::construct(m_alloc, newptr + i, std::move(m_data[i]));
-            alloc_traits::destroy(m_alloc, m_data + i);
+                alloc_traits::construct(_alloc(), newptr + i, std::move(_data()[i]));
+            alloc_traits::destroy(_alloc(), _data() + i);
         }
 
-        alloc_traits::deallocate(m_alloc, m_data, m_capacity);
-        m_data = newptr;
+        alloc_traits::deallocate(_alloc(), _data(), m_capacity);
+        _data() = newptr;
         m_capacity = n;
     }
 
@@ -120,10 +125,10 @@ private:
 public:
     constexpr vector(void)
         noexcept(noexcept(Allocator()))
-        : m_data(), m_size(), m_capacity(), m_alloc() {}
+        : m_data{impl::default_construct_t{}}, m_size(), m_capacity() {}
 
     constexpr explicit vector(const Allocator& alloc) noexcept
-        : m_data(), m_size(), m_capacity(), m_alloc(alloc) {}
+        : m_data{nullptr, alloc}, m_size(), m_capacity() {}
 
     constexpr vector(size_type n, const T& val,
         const Allocator& alloc = Allocator())
@@ -141,23 +146,22 @@ public:
 
     constexpr vector(const vector& other)
         : vector(std::allocator_traits<allocator_type>::
-            select_on_container_copy_construction(other.m_alloc))
+            select_on_container_copy_construction(other._alloc()))
     { insert(cbegin(), other.begin(), other.end()); }
 
     constexpr vector(const vector& other, const Allocator& alloc)
         : vector(alloc) { insert(cbegin(), other.begin(), other.end()); }
 
     constexpr vector(vector&& other) noexcept
-        : m_data(std::exchange(other.m_data, nullptr))
+        : m_data{std::exchange(other._data(), nullptr), std::move(other._alloc())}
         , m_size(std::exchange(other.m_size, 0))
-        , m_capacity(std::exchange(other.m_capacity, 0))
-        , m_alloc(std::move(other.m_alloc)) {}
+        , m_capacity(std::exchange(other.m_capacity, 0)) { }
 
     constexpr vector(vector&& other, const Allocator& alloc)
         : vector(alloc)
     {
-        if (alloc == other.get_allocator()) {
-            m_data = std::exchange(other.m_data, nullptr);
+        if (alloc == other._alloc()) {
+            _data() = std::exchange(other._data(), nullptr);
             m_size = std::exchange(other.m_size, 0);
             m_capacity = std::exchange(other.m_capacity, 0);
         } else {
@@ -185,9 +189,9 @@ public:
 
         if constexpr (alloc_traits::
             propagate_on_container_copy_assignment::value) {
-            if (m_alloc != other.m_alloc)
+            if (_alloc() != other._alloc())
                 shrink_to_fit();
-            m_alloc = other.m_alloc;
+            _alloc() = other._alloc();
         }
 
         insert(cbegin(), other.begin(), other.end());
@@ -201,10 +205,10 @@ public:
         if constexpr (alloc_traits::
             propagate_on_container_move_assignment::value) {
             shrink_to_fit();
-            m_alloc = std::move(other.m_alloc);
+            _alloc() = std::move(other._alloc());
         }
         else {
-            if (m_alloc != other.m_alloc) {
+            if (_alloc() != other._alloc()) {
                 // TODO: std::move_iterator
                 for (auto& item : other)
                     emplace_back(std::move(item));
@@ -213,7 +217,7 @@ public:
             shrink_to_fit();
         }
 
-        m_data = std::exchange(other.m_data, nullptr);
+        _data() = std::exchange(other._data(), nullptr);
         m_size = std::exchange(other.m_size, 0);
         m_capacity = std::exchange(other.m_capacity, 0);
         return *this;
@@ -245,55 +249,55 @@ public:
     }
 
     constexpr allocator_type get_allocator(void) const noexcept
-    { return m_alloc; }
+    { return _alloc(); }
 
     constexpr reference at(size_type pos)
     {
         // TODO: exceptions
         // if (pos >= sz)
         //     throw std::out_of_range("vector::at");
-        return m_data[pos];
+        return _data()[pos];
     }
     constexpr const_reference at(size_type pos) const
     {
         // TODO: exceptions
         // if (pos >= sz)
         //     throw std::out_of_range("vector::at");
-        return m_data[pos];
+        return _data()[pos];
     }
 
     constexpr reference operator[](size_type pos) noexcept
-    { return m_data[pos]; }
+    { return _data()[pos]; }
     constexpr const_reference operator[](size_type pos) const noexcept
-    { return m_data[pos]; }
+    { return _data()[pos]; }
 
     constexpr reference front() noexcept
-    { return m_data[0]; }
+    { return _data()[0]; }
     constexpr const_reference front() const noexcept
-    { return m_data[0]; }
+    { return _data()[0]; }
     constexpr reference back() noexcept
-    { return m_data[m_size - 1]; }
+    { return _data()[m_size - 1]; }
     constexpr const_reference back() const noexcept
-    { return m_data[m_size - 1]; }
+    { return _data()[m_size - 1]; }
 
     constexpr T* data(void) noexcept
-    { return m_data; }
+    { return _data(); }
     constexpr const T* data(void) const noexcept
-    { return m_data; }
+    { return _data(); }
 
     // TODO: std::reverse_iterator
     constexpr iterator begin() noexcept
-    { return iterator { m_data }; }
+    { return iterator { _data() }; }
     constexpr const_iterator begin() const noexcept
-    { return const_iterator { m_data }; }
+    { return const_iterator { _data() }; }
     constexpr const_iterator cbegin() const noexcept
-    { return const_iterator { m_data }; }
+    { return const_iterator { _data() }; }
     constexpr iterator end() noexcept
-    { return iterator { m_data + m_size }; }
+    { return iterator { _data() + m_size }; }
     constexpr const_iterator end() const noexcept
-    { return const_iterator { m_data + m_size }; }
+    { return const_iterator { _data() + m_size }; }
     constexpr const_iterator cend() const noexcept
-    { return const_iterator { m_data + m_size }; }
+    { return const_iterator { _data() + m_size }; }
 
     [[nodiscard]] constexpr bool empty() const noexcept
     { return m_size == 0; }
@@ -332,22 +336,22 @@ public:
     template <typename... Args>
     constexpr iterator emplace(const_iterator pos, Args&&... args)
     {
-        size_type idx = pos - m_data;
+        size_type idx = pos - _data();
 
-        if (!m_data)
+        if (!_data())
             reserve(1);
 
         if (m_size == m_capacity)
             reserve(m_capacity * 2);
 
         for (size_type i = m_size; i > idx; --i)
-            alloc_traits::construct(m_alloc, m_data + i, std::move(m_data[i-1]));
+            alloc_traits::construct(_alloc(), _data() + i, std::move(_data()[i-1]));
 
-        alloc_traits::construct(m_alloc, m_data + idx,
+        alloc_traits::construct(_alloc(), _data() + idx,
             std::forward<Args>(args)...);
 
         ++m_size;
-        return iterator { m_data + idx };
+        return iterator { _data() + idx };
     }
 
     constexpr iterator insert(const_iterator pos, T&& val)
@@ -360,18 +364,18 @@ public:
         if (!n)
             return pos;
 
-        size_type idx = pos - m_data;
+        size_type idx = pos - _data();
         if (!pos)
             reserve(n);
 
         if (m_size + n > m_capacity)
             reserve(m_size + n);
         for (size_type i = m_size + n - 1; i >= idx + n; --i)
-            alloc_traits::construct(m_alloc, m_data + i, std::move(m_data[i-n]));
+            alloc_traits::construct(_alloc(), _data() + i, std::move(_data()[i-n]));
         for (size_type i = idx; i < idx + n; ++i)
-            alloc_traits::construct(m_alloc, m_data + i, val);
+            alloc_traits::construct(_alloc(), _data() + i, val);
         m_size += n;
-        return iterator { m_data + idx };
+        return iterator { _data() + idx };
     }
 
     // TODO: LegacyInputIterator version of this
@@ -379,7 +383,7 @@ public:
     constexpr iterator insert(const_iterator pos,
         ForwardIter first, ForwardIter last)
     {
-        size_type idx = pos - m_data;
+        size_type idx = pos - _data();
         size_type n = 0;
 
         ForwardIter tmp = first;
@@ -395,11 +399,11 @@ public:
         if (m_size + n > m_capacity)
             reserve(m_size + n);
         for (size_type i = m_size + n - 1; i >= idx + n; --i)
-            alloc_traits::construct(m_alloc, m_data + i, std::move(m_data[i-n]));
+            alloc_traits::construct(_alloc(), _data() + i, std::move(_data()[i-n]));
         for (size_type i = idx; i < idx + n; ++i)
-            alloc_traits::construct(m_alloc, m_data + i, *first++);
+            alloc_traits::construct(_alloc(), _data() + i, *first++);
         m_size += n;
-        return iterator { m_data + idx };
+        return iterator { _data() + idx };
     }
 
     constexpr iterator insert(const_iterator pos, std::initializer_list<T> init)
@@ -407,12 +411,12 @@ public:
 
     constexpr iterator erase(const_iterator pos)
     {
-        size_type idx = pos - m_data;
-        alloc_traits::destroy(m_alloc, m_data + idx);
+        size_type idx = pos - _data();
+        alloc_traits::destroy(_alloc(), _data() + idx);
         for (size_type i = idx; i < m_size - 1; ++i)
-            alloc_traits::construct(m_alloc, m_data + i, std::move(m_data[i+1]));
+            alloc_traits::construct(_alloc(), _data() + i, std::move(_data()[i+1]));
         --m_size;
-        return iterator { m_data + idx };
+        return iterator { _data() + idx };
     }
 
     constexpr iterator erase(const_iterator first, const_iterator last)
@@ -421,15 +425,15 @@ public:
         if (!n)
             return last;
 
-        size_type idx = first - m_data;
+        size_type idx = first - _data();
         for (size_type i = idx; i < idx + n; ++i)
-            alloc_traits::destroy(m_alloc, m_data + i);
+            alloc_traits::destroy(_alloc(), _data() + i);
 
         for (size_type i = idx; i < m_size - n; ++i)
-            m_alloc.construct(m_data + i, std::move(m_data[i+n]));
+            _alloc().construct(_data() + i, std::move(_data()[i+n]));
 
         m_size -= n;
-        return iterator { m_data + idx };
+        return iterator { _data() + idx };
     }
 
     constexpr void push_back(const T& val) { insert(cend(), val); }
@@ -446,8 +450,8 @@ public:
         || alloc_traits::is_always_equal::value)
     {
         if (alloc_traits::propagate_on_container_swap::value)
-            std::swap(m_alloc, other.m_alloc);
-        std::swap(m_data, other.m_data);
+            std::swap(_alloc(), other.m_alloc);
+        std::swap(_data(), other.m_data);
         std::swap(m_size, other.m_size);
         std::swap(m_capacity, other.m_capacity);
     }