From: Tomasz KamiƄski <[email protected]>

Constructor and assigment are not implemented, as they depends
on above.
---
This is a forge pull request published on the gcc-patches mailing list mailing 
list
as requested by tkaminsk via Sourceware Forge 
<[email protected]>.
Forge discussion: https://forge.sourceware.org/gcc/gcc/pulls/224

Get it locally using:
```
git fetch forge-upstream "+refs/versioned_pull/224/*:refs/versioned_pull/224/*"
git switch -c "pr-224-v1" "refs/versioned_pull/224/1/head"
```
Or, download the patch at: https://forge.sourceware.org/gcc/gcc/pulls/224.diff
Created on: 2026-08-25 09:57:22+00:00
Latest update: 2026-08-25 10:18:25+00:00
Changes: 4 changed files, 1438 additions, 0 deletions
Head revision: tkaminsk/gcc ref tk/hive commit 
6a9eeea6b3648750c3507c399319a1182ca1ded2 
Base revision: gcc/gcc ref trunk commit 
70ebcf89f8534fe410163415f18c527b7b694b0b r17-3477-g70ebcf89f8534f
Merge base: 70ebcf89f8534fe410163415f18c527b7b694b0b
Requested Reviewers: 

Changed files:
- A: hive.cpp
- A: libstdc++-v3/include/bits/hive.h
- M: libstdc++-v3/include/Makefile.am
- M: libstdc++-v3/include/Makefile.in

 hive.cpp                         |  143 ++++
 libstdc++-v3/include/Makefile.am |    1 +
 libstdc++-v3/include/Makefile.in |    1 +
 libstdc++-v3/include/bits/hive.h | 1293 ++++++++++++++++++++++++++++++
 4 files changed, 1438 insertions(+)
 create mode 100644 hive.cpp
 create mode 100644 libstdc++-v3/include/bits/hive.h

diff --git a/hive.cpp b/hive.cpp
new file mode 100644
index 0000000000000..0616051e1e1d7
--- /dev/null
+++ b/hive.cpp
@@ -0,0 +1,143 @@
+#include <iostream>
+#include <bits/hive.h>
+#include <ranges>
+#include <vector>
+
+static_assert(std::forward_iterator<std::hive<int>::iterator>);
+static_assert(std::ranges::range<std::hive<int>&>);
+
+void iterate(const std::hive<long long>& h)
+{
+  std::cout << "-- Forward: " << std::endl;
+  for (auto it = h.begin(), e = h.end(); it != e; ++it)
+    std::cout << *it << std::endl;
+  std::cout << "-- Backward: " << std::endl;
+  for (auto it = h.end(), b = h.begin(); it != b;)
+    std::cout << *--it << std::endl;
+}
+
+void insert(std::hive<long long>& h)
+{
+  for (int i = 10; i < 100; i+= 10)
+   for (int j = 9; j > 0; j -= 2)
+     {
+       std::cout << "Emplace " << (i+j) << std::endl;
+        h.emplace(i + j);
+     }
+}
+
+int main()
+{
+  std::hive<long long> h;
+  insert(h);
+  iterate(h);
+
+  int r = 0;
+  while (!h.empty())
+  {
+    std::cout << "---- Erase round: " << ++r << std::endl;
+    for (auto it = h.begin(), e = h.end(); it != e;)
+      {
+        std::cout << "Erase: " << *it << std::endl;
+        it = h.erase(it);
+        if (it == e)
+         break;
+        std::cout << "Keep: " << *it++ << std::endl;
+      }
+    std::cout << "- After erase " << std::endl;
+    for (auto it = h.begin(), e = h.end(); it != e; ++it)
+      std::cout << *it << std::endl;
+  }
+
+  r = 0;
+  insert(h);
+  iterate(h);
+
+  int n = 20;
+  while (!h.empty())
+  {
+    std::cout << "---- Erase decreasing bulk round: " << ++r << std::endl;
+    for (auto it = h.begin(), e = h.end(); it != e;)
+      {
+        std::cout << "Erase: " << *it << " + " << n << std::endl;
+       auto next = it;
+       std::ranges::advance(next, n, e);
+       it = h.erase(it, next);
+       std::cout << "Size after: " << h.size() << std::endl;
+        if (it == e)
+         break;
+
+       std::cout << "Keep: " << *it << " + " << n << std::endl;
+       std::ranges::advance(it, n, e);
+      }
+    std::cout << "- After erase " << std::endl;
+    for (auto it = h.begin(), e = h.end(); it != e; ++it)
+      std::cout << *it << std::endl;
+
+    if (n >= 2) n /= 2;
+  }
+
+  r = 0;
+  insert(h);
+  iterate(h);
+
+  n = 1;
+  while (!h.empty())
+  {
+    std::cout << "---- Erase increasing bulk round: " << ++r << std::endl;
+    for (auto it = h.begin(), e = h.end(); it != e;)
+      {
+        std::cout << "Erase: " << *it << " + " << n << std::endl;
+       auto next = it;
+       std::ranges::advance(next, n, e);
+       it = h.erase(it, next);
+       std::cout << "Size after: " << h.size() << std::endl;
+        if (it == e)
+         break;
+        std::cout << "Keep: " << *it << " + " << n << std::endl;
+       std::ranges::advance(it, n, e);
+      }
+    std::cout << "- After erase " << std::endl;
+    for (auto it = h.begin(), e = h.end(); it != e; ++it)
+      std::cout << *it << std::endl;
+
+    n *= 2;
+  }
+
+  std::vector<long long> v;
+  for (int i = 10; i < 50; i+= 10)
+    for (int j = 9; j > 0; j -= 1)
+      v.push_back(i + j);
+
+  auto tv = [s = std::span(v)](size_t from, size_t count)
+  {
+    size_t offset = from % 10;
+    size_t start = (from / 10 - 1) * 10;
+    return std::views::transform(s.subspan(offset, count), [start](auto v) { 
return v + start; });
+  };
+
+  std::cout << "---- Range insert" << std::endl;
+  h.insert_range(v);
+  h.insert_range(tv(50, 20));
+  h.insert_range(tv(70, 5) | std::views::as_input);
+  h.insert_range(tv(75, 15) | std::views::as_input);
+  iterate(h);
+
+  auto it = h.begin(), nt = it;
+  std::ranges::advance(nt, 60);
+  it = h.erase(it, nt);
+  std::ranges::advance(it, 7);
+  std::ranges::advance(nt = it, 6);
+  it = h.erase(it, nt);
+
+  std::cout << "---- Assinging v" << std::endl;
+  h.assign_range(v);
+  iterate(h);
+
+  h.assign_range(std::vector<int>{});
+  h.assign_range(tv(60, 15));
+
+  std::cout << "---- Assinging v as input" << std::endl;
+  h.assign_range(v | std::views::as_input);
+  iterate(h);
+}
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 3c30aa21d6b55..9c9385cd6f682 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -231,6 +231,7 @@ bits_headers = \
        ${bits_srcdir}/gslice_array.h \
        ${bits_srcdir}/hashtable.h \
        ${bits_srcdir}/hashtable_policy.h \
+       ${bits_srcdir}/hive.h \
        ${bits_srcdir}/indirect.h \
        ${bits_srcdir}/indirect_array.h \
        ${bits_srcdir}/ios_base.h \
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
index d081481293fff..afc3d5bb6b3bf 100644
--- a/libstdc++-v3/include/Makefile.in
+++ b/libstdc++-v3/include/Makefile.in
@@ -587,6 +587,7 @@ bits_freestanding = \
 @GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/gslice_array.h \
 @GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/hashtable.h \
 @GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/hashtable_policy.h \
+@GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/hive.h \
 @GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/indirect.h \
 @GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/indirect_array.h \
 @GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/ios_base.h \
diff --git a/libstdc++-v3/include/bits/hive.h b/libstdc++-v3/include/bits/hive.h
new file mode 100644
index 0000000000000..a96aa113559a8
--- /dev/null
+++ b/libstdc++-v3/include/bits/hive.h
@@ -0,0 +1,1293 @@
+// Hive implementation -*- C++ -*-
+
+// Copyright (C) 2026 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file bits/hive.h
+ *  This is an internal header file, included by other library headers.
+ *  Do not attempt to use it directly. @headername{hive}
+ */
+
+#ifndef _BITS_HIVE_H
+#define _BITS_HIVE_H 1
+
+#include <bits/stl_iterator_base_funcs.h>
+#include <bits/stdexcept_throw.h>
+#include <initializer_list>
+#include <compare>
+#include <bit>
+#include <bits/align.h>
+#include <bits/ranges_base.h>          // ranges::distance
+#include <bits/ranges_algobase.h>      // ranges::copy
+#include <bits/ranges_util.h>          // ranges::subrange
+
+#include <debug/assertions.h>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
+
+struct hive_limits
+{
+  constexpr
+  hive_limits(size_t __min, size_t __max) noexcept
+  : min(__min), max(__max)
+  { }
+
+  size_t min;
+  size_t max;
+};
+
+
+template<typename _Tp, typename _Allocator = allocator<_Tp>>
+  class hive;
+
+namespace __hive
+{
+  struct _IgnorePtr
+  {
+    constexpr
+    _IgnorePtr(nullptr_t)
+    { }
+
+    template<typename _Tp>
+    constexpr
+    _IgnorePtr(const volatile _Tp*)
+    { }
+  };
+
+  template<size_t _Bytes>
+    struct _Counter
+    {
+      static consteval auto
+      _S_select_size()
+      {
+#ifdef __UINT64_TYPE__
+        if constexpr (_Bytes == 8)
+          return static_cast<__UINT64_TYPE__>(0);
+        else
+#endif
+#ifdef __UINT32_TYPE__
+        if constexpr (_Bytes == 4)
+          return static_cast<__UINT32_TYPE__>(0);
+        else
+#endif
+#ifdef __UINT16_TYPE__
+        if constexpr (_Bytes == 2)
+          return static_cast<__UINT16_TYPE__>(0);
+        else
+#endif
+        if constexpr (_Bytes == 1)
+          return static_cast<unsigned char>(0);
+        else
+          static_assert("Unsupported bytes count");
+      }
+
+      using _SizeT = decltype(_S_select_size());
+
+      static consteval size_t
+      max_size()
+      {
+        if constexpr (_Bytes >= 8)
+          return (size_t(1) << 48) - 1;
+        else if constexpr (_Bytes >= 4)
+          return (size_t(1) << 24) - 1;
+        else if constexpr (_Bytes >= 2)
+          return (size_t(1) << 12) - 1;
+        else
+          return 255;
+      }
+
+      static constexpr unsigned char _S_contb = 0x40;
+      static constexpr unsigned char _S_vmask = _S_contb - 1;
+
+      static _SizeT
+      _S_load_high(const unsigned char* __ptr)
+      {
+        _SizeT __res(*__ptr & _S_vmask);
+        if constexpr (_Bytes >= 2)
+          __res |= (_SizeT(__ptr[1] & _S_vmask) << 6);
+        if constexpr (_Bytes >= 4)
+          {
+            __res |= (_SizeT(__ptr[2] & _S_vmask) << 12);
+            __res |= (_SizeT(__ptr[3] & _S_vmask) << 18);
+          }
+        if constexpr (_Bytes >= 8)
+          {
+            __res |= (_SizeT(__ptr[4] & _S_vmask) << 24);
+            __res |= (_SizeT(__ptr[5] & _S_vmask) << 30);
+            __res |= (_SizeT(__ptr[6] & _S_vmask) << 36);
+            __res |= (_SizeT(__ptr[7] & _S_vmask) << 42);
+          }
+         return __res;
+      }
+
+      [[__gnu__::__always_inline__]]
+      static _SizeT
+      _S_load_fwd(const unsigned char* __ptr)
+      {
+        if constexpr (_Bytes == 1)
+          return _SizeT(*__ptr);
+        else if (!(*__ptr & _S_contb))
+          return _SizeT(*__ptr & _S_vmask);
+        else
+          return _S_load_high(__ptr);
+      }
+
+      [[__gnu__::__always_inline__]]
+      static _SizeT
+      _S_load_bwd(const unsigned char* __ptr)
+      {
+        if constexpr (_Bytes == 1)
+          return _SizeT(*__ptr);
+        else if (!(*__ptr & _S_contb))
+          return _SizeT(*__ptr & _S_vmask);
+        else
+          return _S_load_high(__ptr + 1 - _Bytes);
+      }
+
+      static void
+      _S_store_high(unsigned char* __ptr, _SizeT __val)
+      {
+        *__ptr = (_S_contb | (__val & 0x3f));
+        if constexpr (_Bytes >= 2)
+          __ptr[1] = (_S_contb | ((__val >> 6) & _S_vmask));
+        if constexpr (_Bytes >= 4)
+          {
+            __ptr[2] = (_S_contb | ((__val >> 12) & _S_vmask));
+            __ptr[3] = (_S_contb | ((__val >> 18) & _S_vmask));
+          }
+        if constexpr (_Bytes >= 8)
+          {
+            __ptr[4] = (_S_contb | ((__val >> 24) & _S_vmask));
+            __ptr[5] = (_S_contb | ((__val >> 30) & _S_vmask));
+            __ptr[6] = (_S_contb | ((__val >> 36) & _S_vmask));
+            __ptr[7] = (_S_contb | ((__val >> 42) & _S_vmask));
+          }
+      }
+
+      [[__gnu__::__always_inline__]]
+      static void
+      _S_store(unsigned char* __ptr, _SizeT __val)
+      {
+        if constexpr (_Bytes == 1)
+          __ptr[0] = __ptr[__val-1] = __val;
+        else if (__val <= _S_vmask)
+          __ptr[0] = __ptr[__val-1] = __val;
+        else
+          {
+            _S_store_high(__ptr, __val);
+            _S_store_high(__ptr - __val - _Bytes, __val);
+          }
+      }
+    };
+
+  // Represents an metada about the memory block. Each memory
+  // block consits of:
+  //  * block metadata (_Block object)
+  //  * skipfields (_M_capacity bytes)
+  //  * slots (_M_capacity _Slot)
+  // Are of them are placed in single memory chunk of _M_capacity
+  // + _S_extra_slots(_M_capacity) elements, as follows
+  //
+  // | <- _S_extra_slots(_M_capacity)                                 --> |
+  // | <- __for_align_ --> | <-- __for_block -> | <-- _for_skipfields --> | 
<-- _M_capacity --> |
+  // [    align   ][ _Block         ][ skipfields               ]         [ 
slots               ]
+  //
+  // The address of the chunk (if needed) is stored inside block can be
+  // retrived by _M_memory(). The member is optimized out if it can be
+  // restored from block address (there is not algigment).
+  //
+  // Each of the slot either contains element (_M_val) or is empty,
+  // occupied elemnts has their corresponding skipfield by set to
+  // 0xff.
+  //
+  // Continous ranges of the empty slot, form a double linked list,
+  // that are indicated by positions of previous and next node
+  // (npos is used to indicate first/last node). The head of the
+  // list is _M_free_head member. The size of the range is encoded
+  // in the edge bytes of skipfields, allow O(1) skipping.
+  //
+  // The _Blocks are member of intriusive list represented by
+  // _Block_list and _M_next, _M_prev, _M_next_free members
+  // facilitate that.
+  template<typename _Tp, typename _Counter, typename _Ptr>
+    struct _Block
+    {
+      using _CounterT = _Counter;
+      using _SizeT = typename _CounterT::_SizeT;
+      static constexpr _SizeT npos = ~_SizeT(0);
+
+      struct _Free_node
+      {
+        _SizeT _M_next;
+        _SizeT _M_prev;
+      };
+
+      union _Slot
+      {
+        _Tp _M_val;
+        _Free_node _M_free;
+      };
+
+      struct _Reservation
+      {
+        _SizeT _M_pos;
+        _SizeT _M_capacity;
+        _SizeT _M_next;
+      };
+
+      using _Alloc_ptr = __ptr_rebind<_Ptr, _Slot>;
+      using _Mem_ptr = std::conditional_t<
+        // Block is stored at the first byte of allocated memory chunk,
+        // so their pointer value are the same.
+        is_pointer_v<_Ptr> && (alignof(void*) <= alignof(_Slot)),
+        _IgnorePtr, _Alloc_ptr>;
+
+      static constexpr size_t
+      _S_slot_count(size_t __bytes)
+      { return (__bytes + sizeof(_Slot) - 1) / sizeof(_Slot); }
+
+      static constexpr size_t
+      _S_extra_slots(size_t __capacity)
+      {
+        constexpr size_t __align_req = (alignof(_Block) > alignof(_Slot))
+                                       ? alignof(_Block) - alignof(_Slot) : 0;
+        constexpr size_t __for_align = _S_slot_count(__align_req);
+        constexpr size_t __for_block = _S_slot_count(sizeof(_Block));
+        constexpr size_t __block_pad = __for_align * sizeof(_Slot) - 
__align_req
+                                     + __for_block * sizeof(_Slot) - 
sizeof(_Block);
+
+        size_t __for_skipfields
+          = (__capacity > __block_pad) ? _S_slot_count(__capacity - 
__block_pad) : 0;
+        return __for_align + __for_block + __for_skipfields;
+      }
+
+      _Block() = default;
+
+      _Block(_Alloc_ptr __mem, _SizeT __capacity)
+      : _M_mem(__mem), _M_capacity(__capacity)
+      { _M_clear_slots(); }
+
+      _Block* _M_prev = nullptr;
+      _Block* _M_next = nullptr;
+      _Block* _M_next_free = nullptr;
+
+      [[no_unique_address]] _Mem_ptr _M_mem = nullptr;
+      _SizeT _M_capacity = 0;
+      _SizeT _M_free_head = -1;
+
+      [[__gnu__::__always_inline__]]
+      bool
+      _M_sentinel() const noexcept
+      { return _M_capacity == 0; }
+
+      [[__gnu__::__always_inline__]]
+      bool
+      _M_full() const noexcept
+      { return _M_free_head == npos; }
+
+      [[__gnu__::__always_inline__]]
+      bool
+      _M_empty() const noexcept
+      {
+        // TODO: Could also compare _M_skipfield(0) with _M_capacity.
+        return (_M_free_head == 0) && (_M_slot(0)->_M_free._M_next == npos);
+      }
+
+      [[__gnu__::__always_inline__]]
+      _Alloc_ptr
+      _M_memory() const noexcept
+      {
+        if constexpr (is_pointer_v<_Ptr> && (alignof(void*) <= alignof(_Slot)))
+          return reinterpret_cast<_Slot*>(const_cast<_Block*>(this));
+        else
+          return _M_mem;
+      }
+
+      [[__gnu__::__always_inline__]]
+      unsigned char*
+      _M_skipfield(size_t __pos) const noexcept
+      {
+        return reinterpret_cast<unsigned char*>(const_cast<_Block*>(this))
+               + sizeof(_Block) + __pos;
+      }
+
+      [[__gnu__::__always_inline__]]
+      bool
+      _M_occupied(size_t __pos) const noexcept
+      { return *_M_skipfield(__pos) == 0xff; }
+
+      [[__gnu__::__always_inline__]]
+      size_t
+      _M_first_occupied() const noexcept
+      {
+        if (_M_sentinel() || _M_occupied(0))
+          return 0;
+        return _CounterT::_S_load_fwd(_M_skipfield(0));
+      }
+
+      [[__gnu__::__always_inline__]]
+      _Slot*
+      _M_slot(size_t __pos) const noexcept
+      { return std::to_address(_M_memory()) + _S_extra_slots(_M_capacity) + 
__pos; }
+
+      [[__gnu__::__always_inline__]]
+      _Tp*
+      _M_elem(size_t __pos) const noexcept
+      { return std::addressof(_M_slot(__pos)->_M_val); }
+
+      [[__gnu__::__always_inline__]]
+      _Free_node&
+      _M_free_node(size_t __pos) const noexcept
+      { return _M_slot(__pos)->_M_free; }
+
+      // Returns the information about the first range of empty slotents, 
preserving
+      // values stored inside the slot.
+      [[__gnu__::__always_inline__]]
+      _Reservation
+      _M_reserve_slots()
+      {
+        return {_M_free_head,
+                _CounterT::_S_load_fwd(_M_skipfield(_M_free_head)),
+                _M_free_node(_M_free_head)._M_next};
+      }
+
+      // Marks slots in range [__res._M_pos, __res._M_pos + __n), adjusting 
the free list.
+      // Returns true if the block is filled.
+      bool
+      _M_commit_slots(_Reservation __res, size_t __n)
+      {
+        std::fill_n(_M_skipfield(__res._M_pos), __n, 0xff);
+        if (__n < __res._M_capacity)
+          {
+            // Node is partially used, trim it size, and adjust node.
+            _M_free_head += __n;
+            _M_free_node(_M_free_head) = {npos, __res._M_next};
+            _CounterT::_S_store(_M_skipfield(_M_free_head), __res._M_capacity 
- __n);
+            return false;
+          }
+        else if (__res._M_next != npos)
+          {
+            // Node is fully used, next free node becomes first node.
+            _M_free_head = __res._M_next;
+            _M_free_node(_M_free_head)._M_prev = npos;
+            return false;
+          }
+        else
+          {
+            // Node and block is fully used.
+            _M_free_head = npos;
+            return true;
+          }
+      }
+
+      // Marks are slots as empty, creating single free node
+      // for range [0, _M_capacity)
+      void
+      _M_clear_slots()
+      {
+        std::fill_n(_M_skipfield(0), _M_capacity, 0);
+        _CounterT::_S_store(_M_skipfield(0), _M_capacity);
+        _M_free_node(0) = { npos, npos };
+        _M_free_head = 0;
+      }
+
+      // Marks slot in range [__pos, __pos + __n) as empty, and record them
+      // in free list. Updates __pos to next occupied slot and returns true
+      // if block is empty
+      size_t
+      _M_release_slots(size_t& __pos, size_t __n)
+      {
+        size_t __pfree = 0, __nfree = 0;
+        if ((__pos > 0) && !_M_occupied(__pos - 1))
+          __pfree = _CounterT::_S_load_bwd(_M_skipfield(__pos - 1));
+        if ((__pos + __n < _M_capacity) && !_M_occupied(__pos + __n))
+          __nfree = _CounterT::_S_load_fwd(_M_skipfield(__pos + __n));
+
+        if (__pfree + __nfree + __n == _M_capacity)
+          {
+            // All slots in blocks become empty, simply clear the block.
+            _M_clear_slots();
+            __pos = _M_capacity;
+            return true;
+          }
+
+       auto __link_next = [this](size_t __pos, size_t __next)
+         {
+           if (__pos != npos)
+             _M_free_node(__pos)._M_next = __next;
+           else
+             _M_free_head = __next;
+         };
+
+       auto __link_prev = [this](size_t __pos, size_t __prev)
+         {
+           if (__pos != npos)
+             _M_free_node(__pos)._M_prev = __prev;
+         };
+
+       if (__pfree && __nfree)
+          {
+            // Two free blocks are merged, expand the preceeding one to cover 
all slots.
+            _CounterT::_S_store(_M_skipfield(__pos - __pfree), __pfree + 
__nfree + __n);
+
+            // And then remove the succseeding node from the free list.
+            const _Free_node __next = _M_free_node(__pos + __n);
+            __link_next(__next._M_prev, __next._M_next);
+            __link_prev(__next._M_next, __next._M_prev);
+          }
+        else if (__pfree)
+          // Expand the preceeding slot, already on free list
+          _CounterT::_S_store(_M_skipfield(__pos - __pfree), __pfree + __n);
+        else if (__nfree)
+          {
+            // Expand the succseeding slot, adjusting it start position.
+            _CounterT::_S_store(_M_skipfield(__pos), __nfree + __n);
+            _Free_node& __node = _M_free_node(__pos);
+            __node = _M_free_node(__pos + __n);
+
+            // Adjust start position in previous and sucsseding node.
+            __link_next(__node._M_prev, __pos);
+            __link_prev(__node._M_next, __pos);
+          }
+       else
+          {
+            // New [__pos, __pos + __n) is inside occupied slots range,
+            // created a new slot and corresponding free list node.
+            _CounterT::_S_store(_M_skipfield(__pos), __n);
+            _M_free_node(__pos) = {npos, _M_free_head};
+
+            // Add new node at begining of free list.
+            __link_prev(_M_free_head, __pos);
+            _M_free_head = __pos;
+          }
+
+        __pos += __n + __nfree;
+        return false;
+      }
+
+      [[__gnu__::__always_inline__]]
+      void
+      _M_set_next(_Block* __node)
+      {
+        _M_next = __node;
+        if (__node)
+          __node->_M_prev = this;
+      }
+    };
+
+
+  // Class representing an double linked list of blocks. Manages the block
+  // itself, but not contained elements.
+  //
+  // The blocks are split into two kinds:
+  // * active [_M_first, _M_sent): contains at least one element, visited
+  //   by iteration
+  // * reserved (_M_sent, null): no element contained, provded extra capacity
+  // The blocks are moved between list by hiding (active -> reserved) or
+  // exposing (reserved->active).
+  //
+  // Futhermore, the reserved blocks and the subset of active list, that 
contains
+  // at least one free slot, are forming single linked list (_M_next_free),
+  // starting at _M_free_head() (which is _M_sent._M_next_free).
+  template<typename _Tp, typename _Allocator>
+    struct _Block_list
+    {
+      static consteval size_t
+      _S_counter_bytes()
+      {
+        size_t __max = sizeof(_Tp) / 2;
+#ifdef __UINT64_TYPE__
+        if (__max >= 8)
+          return 8;
+        else
+#endif
+#ifdef __UINT32_TYPE__
+        if (__max >= 4)
+          return 4;
+        else
+#endif
+#ifdef __UINT16_TYPE__
+        if  (__max >= 2)
+          return 2;
+        else
+#endif
+          return 1;
+      }
+
+      using _CounterT = _Counter<_S_counter_bytes()>;
+      using _SizeT = typename _CounterT::_SizeT;
+      using _BlockT = _Block<_Tp, _CounterT, typename 
allocator_traits<_Allocator>::pointer>;
+      using _SlotT = typename _BlockT::_Slot;
+ 
+      using _SAlloc = typename allocator_traits<_Allocator>::template 
rebind_alloc<_SlotT>;
+      using _SAllocTraits = typename allocator_traits<_Allocator>::template 
rebind_traits<_SlotT>;
+
+      static consteval hive_limits
+      _S_hard_limits()
+      {
+        return {1, 10};
+
+        size_t __alloc_max;
+        if constexpr (requires { _SAlloc::max_size(); })
+          __alloc_max = _SAlloc::max_size();
+        else
+          __alloc_max = numeric_limits<typename 
_SAllocTraits::size_type>::max()
+                          / sizeof(_SlotT);
+
+        constexpr size_t __counter_max = _CounterT::max_size();
+        if  (__alloc_max - __counter_max >= 
_BlockT::_S_extra_slots(__counter_max))
+          return hive_limits(1, __counter_max);
+        else
+          {
+            size_t __max = __alloc_max;
+            if constexpr (alignof(_BlockT) > alignof(_SlotT))
+              __max -= _BlockT::_S_slot_count(alignof(_BlockT) - 
alignof(_SlotT));
+            __max -= _BlockT::_S_slot_count(sizeof(_BlockT));
+
+            __max = (__max * sizeof(_SlotT)) / (sizeof(_SlotT) + 1);
+            return hive_limits(1, __max);
+          }          
+      }
+
+      static consteval hive_limits
+      _S_default_limits()
+      {
+        auto __hard = _S_hard_limits();
+        if (__hard.max < 16)
+          return __hard;
+        else if (__hard.max < 255)
+          return hive_limits(16, __hard.max);
+        else if (__hard.max < 512)
+          return hive_limits(16, 255);
+        else
+          return hive_limits(16, 512);
+      }
+
+      _BlockT _M_sent = _BlockT();
+      _BlockT* _M_first = &_M_sent;
+      hive_limits _M_limits = _S_default_limits();
+      size_t _M_capacity = 0;
+      size_t _M_last_capacity = _S_default_limits().min;
+      [[no_unique_address]] _Allocator _M_alloc;
+
+      ~_Block_list()
+      {
+        _SAlloc __salloc(_M_alloc);
+
+        _BlockT* __block = _M_first;
+        while (__block)
+          {
+            _BlockT* __cur = __block;
+            auto __ptr = __cur->_M_memory();
+            auto __count = __cur->_M_capacity;
+            __block = __block->_M_next;
+
+            // Skip sentinel node
+            if (__cur->_M_sentinel())
+              continue;
+
+            // Custom pointer may have non-trivial destructor, call it before 
releasing
+            // memory.
+            __cur->~_BlockT();
+            __count += _BlockT::_S_extra_slots(__count);
+            _SAllocTraits::deallocate(__salloc, __ptr, __count);
+          }
+      }
+
+      [[__gnu__::__always_inline__]]
+      _BlockT*
+      _M_free_head() const noexcept
+      { return _M_sent._M_next_free; }
+
+      [[__gnu__::__always_inline__]]
+      void
+      _M_pop_free()
+      { _M_sent._M_next_free = _M_sent._M_next_free->_M_next_free; }
+
+      [[__gnu__::__always_inline__]]
+      void
+      _M_append_free(_BlockT* __block)
+      {
+        __block->_M_next_free = _M_sent._M_next_free;
+        _M_sent._M_next_free = __block;
+      }
+
+      void
+      _M_expose(_BlockT* __first, _BlockT* __last)
+      {
+        __first->_M_prev->_M_set_next(__last->_M_next);
+
+        _M_link_prev(_M_sent, __first);
+        __last->_M_set_next(&_M_sent);
+      }
+
+      [[__gnu__::__always_inline__]]
+      void
+      _M_expose(_BlockT* __block)
+      { _M_expose(__block, __block); }
+
+      void
+      _M_hide(_BlockT* __first, _BlockT* __last)
+      {
+        _M_link_prev(*__first, __last->_M_next);
+        _M_append_reserved(__first, __last);
+      }
+
+      [[__gnu__::__always_inline__]]
+      void
+      _M_hide(_BlockT* __block)
+      { _M_hide(__block, __block); }
+
+      _BlockT*
+      _M_reserve_block(size_t __capacity)
+      {
+        _SAlloc __salloc(_M_alloc);
+
+        _BlockT* __block = _M_allocate_block(__salloc, __capacity);
+        _M_append_reserved(__block, __block);
+        _M_append_free(__block);
+        _M_capacity += __capacity;
+        return __block;
+      }
+
+      _BlockT*
+      _M_reserve_block()
+      {
+        _M_last_capacity *= 2;
+        if (_M_last_capacity > _M_limits.max)
+          _M_last_capacity = _M_limits.max;
+        return _M_reserve_block(_M_last_capacity);
+      }
+
+    private:
+      static _BlockT*
+      _M_allocate_block(_SAlloc& __alloc, size_t __capacity)
+      {
+        const size_t __count = __capacity + 
_BlockT::_S_extra_slots(__capacity);
+        auto __mem = _SAllocTraits::allocate(__alloc, __count);
+
+        void* __ptr = std::to_address(__mem);
+        size_t __space = __count * sizeof(_SlotT);
+        if constexpr (alignof(_BlockT) > sizeof(_SlotT))
+          __ptr = std::align(alignof(_BlockT), sizeof(_BlockT), __ptr, 
__space);
+
+        return ::new(__ptr) _BlockT(__mem, __capacity);
+      }
+
+      [[__gnu__::__always_inline__]]
+      void
+      _M_link_prev(_BlockT& __of, _BlockT* __to)
+      {
+        if (_BlockT* __prev = __of._M_prev)
+          __prev->_M_set_next(__to);
+        else
+          {
+            // __of is first block, set __to as first
+            _M_first = __to;
+            __to->_M_prev = nullptr;
+          }
+      }
+
+      void
+      _M_append_reserved(_BlockT* __first, _BlockT* __last)
+      {
+        __last->_M_set_next(_M_sent._M_next);
+        _M_sent._M_set_next(__first);
+      }
+    };
+
+  template<typename _Tp, typename _BlockT>
+    struct _Iterator
+    {
+      using _CounterT = typename _BlockT::_CounterT;
+
+    public:
+      using iterator_category = bidirectional_iterator_tag;
+      using value_type = _Tp;
+      using pointer = _Tp*;
+      using reference = _Tp&;
+      using size_type = size_t;
+      using difference_type = ptrdiff_t;
+
+      _Iterator() = default;
+
+      template<typename _Up>
+        requires is_const_v<_Tp> && is_same_v<_Tp, const _Up>
+        _Iterator(_Iterator<_Up, _BlockT> __other)
+        : _M_block(__other._M_block), _M_pos(__other._M_pos)
+        { }
+
+      reference
+      operator*() const noexcept
+      { return _M_block->_M_slot(_M_pos)->_M_val; }
+
+      pointer
+      operator->() const noexcept
+      { return _M_block->_M_elem(_M_pos); }
+
+      _Iterator&
+      operator++()
+      {
+        ++_M_pos;
+        if (_M_pos != _M_block->_M_capacity)
+          {
+            if (_M_block->_M_occupied(_M_pos))
+              return *this;
+
+            _M_pos += _CounterT::_S_load_fwd(_M_block->_M_skipfield(_M_pos));
+            if (_M_pos != _M_block->_M_capacity)
+              return *this;
+          }
+
+        _M_block = _M_block->_M_next;
+        _M_pos = _M_block->_M_first_occupied();
+        return *this;
+      }
+
+      _Iterator
+      operator++(int)
+      {
+        _Iterator __res = *this;
+        ++*this;
+        return __res;
+      }
+
+      _Iterator&
+      operator--()
+      {
+        if (_M_pos)
+          {
+            --_M_pos;
+            if (_M_block->_M_occupied(_M_pos))
+              return *this;
+
+            _M_pos -= _CounterT::_S_load_bwd(_M_block->_M_skipfield(_M_pos));
+            if (_M_pos)
+              return *this;
+          }
+
+        _M_block = _M_block->_M_prev;
+        __glibcxx_assert(_M_block);
+        _M_pos = _M_block->_M_capacity - 1;
+        if (_M_block->_M_occupied(_M_pos))
+          return *this;
+
+        _M_pos -= _CounterT::_S_load_bwd(_M_block->_M_skipfield(_M_pos));
+        return *this;
+      }
+
+      _Iterator
+      operator--(int)
+      {
+        _Iterator __res = *this;
+        --*this;
+        return __res;
+      }
+
+      friend bool operator==(_Iterator, _Iterator) = default;
+
+    private:
+      explicit
+      _Iterator(const _BlockT* __block)
+      : _M_block(__block), _M_pos(__block->_M_first_occupied())
+      { }
+
+      explicit
+      _Iterator(const _BlockT* __block, size_t __pos)
+      : _M_block(__block), _M_pos(__pos)
+      { }
+
+      const _BlockT* _M_block = nullptr;
+      size_t _M_pos = 0;
+
+      friend struct _Iterator<const _Tp, _BlockT>;
+      template<typename, typename>
+        friend class _GLIBCXX_STD_C::hive;
+    };
+} // namespace __hive
+
+template<typename _Tp, typename _Allocator>
+  class hive
+  {
+    using _BlockListT = __hive::_Block_list<_Tp, _Allocator>;
+    using _BlockT = typename _BlockListT::_BlockT;
+    using _CounterT = typename _BlockListT::_CounterT;
+    using _AllocT = allocator_traits<_Allocator>;
+
+  public:
+    using size_type = size_t;
+    using difference_type = ptrdiff_t;
+    using iterator = __hive::_Iterator<_Tp, _BlockT>;
+    using const_iterator = __hive::_Iterator<const _Tp, _BlockT>;
+
+    hive() = default;
+
+    ~hive()
+    {
+      if (empty())
+        return;
+
+      _BlockT* __block = _M_blocks._M_first;
+      while (__block != &_M_blocks._M_sent)
+        {
+          _M_clear(__block);
+          __block = __block->_M_next;
+        }
+    }
+
+    template<__detail::__container_compatible_range<_Tp> _Rg>
+      void
+      assign_range(_Rg&& __rg)
+      {
+       if (empty())
+         return insert_range(__rg);
+
+        auto __it = std::ranges::begin(__rg);
+        auto __end = std::ranges::end(__rg);
+       if (__it == __end)
+         return clear();
+
+       auto __erase_from = [&](_BlockT* __block, size_t __pos)
+         {
+           if (__pos != __block->_M_capacity)
+             erase(const_iterator(__block, __pos), end());
+           else
+             erase(const_iterator(__block->_M_next), end());
+         };
+
+       if constexpr (ranges::sized_range<_Rg>)
+          {
+            const auto __size = size_t(ranges::size(__rg));
+            reserve(__size);
+
+           size_t __assigned = 0;
+           // Assing/inserter elements to existing blocks
+            for (_BlockT* __block = _M_blocks._M_first;
+                !__block->_M_sentinel(); __block = __block->_M_next)
+             if (__assigned == __size)
+               {
+                 erase(const_iterator(__block), end());
+                 return;
+               }
+             else if (__assigned + __block->_M_capacity > __size)
+               {
+                 // Block is partially filled, insert until end,
+                 // and then erase from
+                 size_t __last = _M_assign_in_block(__block, __it, __end);
+                 return __erase_from(__block, __last);
+               }
+             else
+               {
+                  // Fully assign block, we do not need to check end
+                 _M_assign_in_block(__block, __it, unreachable_sentinel);
+                 __assigned += __block->_M_capacity;
+               }
+
+           // Insert remaining elements
+           insert_range(ranges::subrange(std::move(__it), __end,
+                                          __size - __assigned));
+         }
+       else
+         {
+            // Fillout existing active blocks
+            for (_BlockT* __block = _M_blocks._M_first;
+                !__block->_M_sentinel(); __block = __block->_M_next)
+             {
+                size_t __last = _M_assign_in_block(__block, __it, __end);
+               if (__it == __end)
+                 return __erase_from(__block, __last);
+             }
+           
+           // Insert remaining elements 
+           insert_range(ranges::subrange(std::move(__it), __end));
+         }
+      }
+
+    iterator
+    begin()
+    { return iterator(_M_blocks._M_first); }
+
+    iterator
+    end()
+    { return iterator(&_M_blocks._M_sent, 0); }
+
+    const_iterator
+    begin() const noexcept
+    { return const_iterator(_M_blocks._M_first); }
+
+    const_iterator
+    end() const noexcept
+    { return const_iterator(&_M_blocks._M_sent, 0); }
+
+    bool
+    empty() const noexcept
+    { return _M_size == 0; }
+
+    size_type
+    size() const noexcept
+    { return _M_size; }
+
+    size_type
+    capacity() const noexcept
+    { return _M_blocks._M_capacity; }
+
+    constexpr hive_limits
+    block_capacity_limits() const noexcept
+    { return _M_blocks._M_limits; }
+
+    void
+    reserve(size_type __n)
+    {
+      if (__n <= capacity())
+        return;
+
+      const hive_limits __limits = _M_blocks._M_limits;
+      for (__n -= capacity(); __n > 2 * __limits.max; __n -= __limits.max)
+        _M_blocks._M_reserve_block(__limits.max);
+
+      if (__n >= __limits.max)
+        {
+          _M_blocks._M_last_capacity = __limits.max;
+
+          // If last block would be smaller than minum limit, try to
+          // split last two blocks equally, to avoid going over capacity
+          if ((__n > __limits.max)
+              && (__n < __limits.max + __limits.min)
+              && (__n >= 2 * __limits.min))
+            {
+              _M_blocks._M_reserve_block(__n / 2);
+              _M_blocks._M_reserve_block(__n - __n / 2);
+              return;
+            }
+
+          _M_blocks._M_reserve_block(__limits.max);
+          __n -= __limits.max;
+        }
+      
+      if (__n >= __limits.min)
+        _M_blocks._M_reserve_block(__n);
+      else if (__n > 0)
+        _M_blocks._M_reserve_block(__limits.min);
+    }
+
+    template<typename... _Args>
+      iterator
+      emplace(_Args&&... __args)
+      {
+        _BlockT* __block;
+        if (_M_size == capacity())
+          __block = _M_blocks._M_reserve_block();
+        else
+          __block = _M_blocks._M_free_head();
+
+        _InsertGuard __guard(*this, __block);
+        __guard.construct(_M_blocks._M_alloc, std::forward<_Args>(__args)...);
+        __guard._M_commit();
+        return iterator(__block, __guard._M_res._M_pos);
+      }
+
+    template<__detail::__container_compatible_range<_Tp> _Rg>
+      void
+      insert_range(_Rg&& __rg)
+      {
+        auto __it = std::ranges::begin(__rg);
+        auto __end = std::ranges::end(__rg);
+       if (__it == __end) [[unlikely]]
+         return;
+
+       if constexpr (ranges::sized_range<_Rg>)
+          {
+            const auto __new_size = _M_size + size_t(ranges::size(__rg));
+            reserve(__new_size);
+
+            _BlockT* __block = _M_blocks._M_free_head();
+            // Fillout initial blocks, we do not need to check against end
+            while (_M_size + __block->_M_capacity <= __new_size)
+              {
+                _M_insert_in_block(__block, __it, unreachable_sentinel);
+                __block = _M_blocks._M_free_head();
+               if (!__block)
+                 return;
+              }
+
+            // Handle block that is partially filled
+            while (__it != __end)
+              _M_insert_in_slot(__block, __it, __end);
+          }
+        else
+          {
+            // Fill out empty spaces in existing blocks.
+            while (_BlockT* __block = _M_blocks._M_free_head())
+              if (_M_insert_in_block(__block, __it, __end))
+                return;
+
+            // Allocate new blocks for remaining elements
+            while (true)
+              {
+                _BlockT* __block = _M_blocks._M_reserve_block();
+                if (_M_insert_in_block(__block, __it, __end))
+                  return;
+              }
+          }
+      }
+
+    iterator
+    erase(const_iterator __it)
+    {
+      _BlockT* __block = const_cast<_BlockT*>(__it._M_block);
+      _BlockT* __next_block = __block->_M_next;
+      size_t __pos = __it._M_pos;
+
+      if (__block->_M_full())
+        _M_blocks._M_append_free(__block);
+
+      _AllocT::destroy(_M_blocks._M_alloc, __block->_M_elem(__pos));
+      _M_size -= 1;
+
+      if (__block->_M_release_slots(__pos, 1))
+        _M_blocks._M_hide(__block);
+
+      if (__pos != __block->_M_capacity)
+        return iterator(__block, __pos);
+      else
+        return iterator(__next_block);
+    }
+
+
+    iterator
+    erase(const_iterator __first, const_iterator __last)
+    {
+      _BlockT* __fblock = const_cast<_BlockT*>(__first._M_block);
+      _BlockT* __lblock = const_cast<_BlockT*>(__last._M_block);
+      if (__fblock == __lblock)
+        {
+          // Erase of range in single block, clear elements if a if any.
+          if (__first._M_pos != __last._M_pos)
+            _M_erase_range(__fblock, __first._M_pos, __last._M_pos);
+          return iterator(__last._M_block, __last._M_pos);
+        }
+
+      // Remove any nodes designated in last block
+      if (auto __lfirst = __lblock->_M_first_occupied(); __last._M_pos != 
__lfirst)
+        _M_erase_range(__lblock, __lfirst, __last._M_pos);
+
+      // If __first block is not fully cleared, remove elements, and move to 
next block
+      if (__first._M_pos != __fblock->_M_first_occupied())
+        {
+          _M_erase_range(__fblock, __first._M_pos, __fblock->_M_capacity);
+          __fblock = __fblock->_M_next;
+          if (__fblock == __lblock)
+            return iterator(__last._M_block, __last._M_pos);
+        }
+
+      // Clear elements in fully erased block, and move to reserved list.
+      _M_clear(__fblock, __lblock);
+      _M_blocks._M_hide(__fblock, __lblock->_M_prev);
+      return iterator(__last._M_block, __last._M_pos);
+    }
+
+    void
+    clear()
+    {
+      if (empty())
+        return;
+
+      _M_clear(_M_blocks._M_first, &_M_blocks._M_sent);
+      _M_blocks._M_hide(_M_blocks._M_first, _M_blocks._M_sent._M_prev);
+    }
+
+  private:
+    struct _InsertGuard
+    {
+      hive& _M_self;
+      _BlockT* _M_block;
+      typename _BlockT::_Reservation _M_res;
+      size_t _M_count = 0;
+
+      _InsertGuard(hive& __self, _BlockT* __block)
+       : _M_self(__self)
+       , _M_block(__block)
+       , _M_res(_M_block->_M_reserve_slots())
+      { }
+
+      [[__gnu__::__always_inline__]]
+      bool
+      _M_filled() const noexcept
+      { return _M_count == _M_res._M_capacity; }
+
+      template<typename... _Args>
+        void
+        construct(_Allocator& __alloc, _Args&&... __args)
+        {
+          auto* __space = _M_block->_M_elem(_M_res._M_pos + _M_count);
+          _AllocT::construct(__alloc, __space, std::forward<_Args>(__args)...);
+          ++_M_count;
+        }
+
+      void
+      _M_commit()
+      {
+        if (_M_block->_M_commit_slots(_M_res, _M_count))
+          _M_self._M_blocks._M_pop_free();
+       // Expose block that was previously reserved
+        if (_M_res._M_capacity == _M_block->_M_capacity)
+          _M_self._M_blocks._M_expose(_M_block);
+
+       _M_self._M_size += _M_count;
+        _M_count = 0;
+      }
+
+      ~_InsertGuard()
+      {
+        if (_M_count)
+          _M_commit();
+      }
+    };
+
+    // Returns position of element after last inserted element, or _M_capacity 
otherwise.
+    template<typename _Iterator, typename _Sentinel>
+      size_t
+      _M_insert_in_slot(_BlockT* __block, _Iterator& __first, _Sentinel __last)
+      {
+        _InsertGuard __guard(*this, __block);
+        while ((__first != __last) && !__guard._M_filled())
+          {
+            __guard.construct(_M_blocks._M_alloc, *__first);
+            ++__first;
+          }
+        return __guard._M_res._M_pos + __guard._M_res._M_capacity;
+      }
+
+    template<typename _Iterator, typename _Sentinel>
+      bool
+      _M_insert_in_block(_BlockT* __block, _Iterator& __first, _Sentinel 
__last)
+      {
+        while (!__block->_M_full())
+          {
+            _M_insert_in_slot(__block, __first, __last);
+            if (__first == __last)
+              return true;
+          }
+        return false;
+      }
+
+    // Returns position of element after last assigned/inserted element, or 
_M_capacity otherwise.
+    template<typename _Iterator, typename _Sentinel>
+      size_t
+      _M_assign_in_block(_BlockT* __block, _Iterator& __first, _Sentinel 
__last)
+      {
+        size_t __pos = 0;
+        while ((__pos != __block->_M_capacity) && (__first != __last))
+          {
+           if (__block->_M_occupied(__pos))
+             {
+               *__block->_M_elem(__pos++) = *__first;
+               ++__first;
+             }
+           else
+              __pos = _M_insert_in_slot(__block, __first, __last);
+         }
+       return __pos;
+      }
+
+    void
+    _M_erase_range(_BlockT* __block, size_t __first, size_t __to)
+    {
+      if (__block->_M_full())
+        _M_blocks._M_append_free(__block);
+
+      auto __release = [&] (size_t __count) {
+        __block->_M_release_slots(__first, __count);
+        _M_size -= __count;
+        return __first;
+      };
+
+      size_t __pos = __first;
+      _AllocT::destroy(_M_blocks._M_alloc, __block->_M_elem(__pos++));
+
+      while (__pos != __to)
+        if (__block->_M_occupied(__pos))
+          _AllocT::destroy(_M_blocks._M_alloc, __block->_M_elem(__pos++));
+        else
+          __pos = __release(__pos - __first);
+
+      if (size_t __count = __pos - __first)
+        __release(__count);
+    }
+
+    void
+    _M_clear(_BlockT* __block)
+    {
+      size_t __pos = 0, __first = 0;
+      while (__pos != __block->_M_capacity)
+        if (__block->_M_occupied(__pos))
+          _AllocT::destroy(_M_blocks._M_alloc, __block->_M_elem(__pos++));
+        else
+          {
+            _M_size -= __pos - __first;
+            __first = __pos + 
_CounterT::_S_load_fwd(__block->_M_skipfield(__pos));
+            __pos = __first;
+          }
+
+      _M_size -= __pos - __first;
+    }
+
+    void
+    _M_clear(_BlockT* __from, _BlockT* __to)
+    {
+      while (__from != __to)
+        {
+          if (__from->_M_full())
+            _M_blocks._M_append_free(__from);
+
+          _M_clear(__from);
+          __from->_M_clear_slots();
+          __from = __from->_M_next;
+        }
+    }
+
+    _BlockListT _M_blocks;
+    size_type _M_size = 0;
+  };
+
+#if __cplusplus >= 201703L
+//  namespace __detail::__variant
+//  {
+//    template<typename> struct _Never_valueless_alt; // see <variant>
+
+    // Provide the strong exception-safety guarantee when emplacing a
+    // vector into a variant, but only if move assignment cannot throw.
+//    template<typename _Tp, typename _Alloc>
+//      struct _Never_valueless_alt<_GLIBCXX_STD_C::vector<_Tp, _Alloc>>
+//      : std::is_nothrow_move_assignable<_GLIBCXX_STD_C::vector<_Tp, _Alloc>>
+//      { };
+//  }  // namespace __detail::__variant
+#endif // C++17
+
+_GLIBCXX_END_NAMESPACE_CONTAINER
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+
+#endif /* _BITS_HIVE_H */
-- 
2.54.0

Reply via email to