I think we should commit this fix from upstream.

https://www.boost.org/users/history/version_1_80_0.html
https://github.com/boostorg/unordered/issues/139

OK? Cheers, Rafael

Index: Makefile
===================================================================
RCS file: /cvs/ports/devel/boost/Makefile,v
retrieving revision 1.130
diff -u -p -u -p -r1.130 Makefile
--- Makefile    29 Aug 2022 17:28:18 -0000      1.130
+++ Makefile    29 Aug 2022 19:28:52 -0000
@@ -2,6 +2,7 @@ NOT_FOR_ARCHS-md = alpha hppa sparc64
 
 COMMENT-main=  free peer-reviewed portable C++ source libraries
 COMMENT-md=    machine-dependent libraries for boost
+REVISION-main= 0
 
 VERSION=       1.80.0
 EPOCH =                0
Index: patches/patch-boost_unordered_detail_fca_hpp
===================================================================
RCS file: patches/patch-boost_unordered_detail_fca_hpp
diff -N patches/patch-boost_unordered_detail_fca_hpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-boost_unordered_detail_fca_hpp        29 Aug 2022 19:28:52 
-0000
@@ -0,0 +1,47 @@
+Boost.Unordered containers are not in a valid state after moving
+https://github.com/boostorg/unordered/issues/139
+
+Index: boost/unordered/detail/fca.hpp
+--- boost/unordered/detail/fca.hpp.orig
++++ boost/unordered/detail/fca.hpp
+@@ -646,7 +646,7 @@ namespace boost {
+ 
+         size_type bucket_count() const { return size_; }
+ 
+-        iterator begin() const { return ++at(size_); }
++        iterator begin() const { return size_ == 0 ? end() : ++at(size_); }
+ 
+         iterator end() const
+         {
+@@ -660,6 +660,10 @@ namespace boost {
+ 
+         local_iterator begin(size_type n) const
+         {
++          if (size_ == 0) {
++            return this->end(n);
++          }
++
+           return local_iterator(
+             (buckets + static_cast<difference_type>(n))->next);
+         }
+@@ -670,12 +674,16 @@ namespace boost {
+ 
+         iterator at(size_type n) const
+         {
+-          std::size_t const N = group::N;
++          if (size_ > 0) {
++            std::size_t const N = group::N;
+ 
+-          iterator pbg(buckets + static_cast<difference_type>(n),
+-            groups + static_cast<difference_type>(n / N));
++            iterator pbg(buckets + static_cast<difference_type>(n),
++              groups + static_cast<difference_type>(n / N));
+ 
+-          return pbg;
++            return pbg;
++          } else {
++            return this->end();
++          }
+         }
+ 
+         span<Bucket> raw()
Index: patches/patch-boost_unordered_detail_implementation_hpp
===================================================================
RCS file: patches/patch-boost_unordered_detail_implementation_hpp
diff -N patches/patch-boost_unordered_detail_implementation_hpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-boost_unordered_detail_implementation_hpp     29 Aug 2022 
19:28:52 -0000
@@ -0,0 +1,84 @@
+Boost.Unordered containers are not in a valid state after moving
+https://github.com/boostorg/unordered/issues/139
+
+Index: boost/unordered/detail/implementation.hpp
+--- boost/unordered/detail/implementation.hpp.orig
++++ boost/unordered/detail/implementation.hpp
+@@ -2054,12 +2054,14 @@ namespace boost {
+ 
+         std::size_t bucket_size(std::size_t index) const
+         {
+-          bucket_iterator itb = buckets_.at(index);
+-          node_pointer n = itb->next;
+           std::size_t count = 0;
+-          while (n) {
+-            ++count;
+-            n = n->next;
++          if (size_ > 0) {
++            bucket_iterator itb = buckets_.at(index);
++            node_pointer n = itb->next;
++            while (n) {
++              ++count;
++              n = n->next;
++            }
+           }
+           return count;
+         }
+@@ -2420,11 +2422,14 @@ namespace boost {
+         node_pointer find_node_impl(
+           Key const& x, bucket_iterator itb) const
+         {
+-          key_equal const& pred = this->key_eq();
+-          node_pointer p = itb->next;
+-          for (; p; p = p->next) {
+-            if (pred(x, extractor::extract(p->value()))) {
+-              break;
++          node_pointer p = node_pointer();
++          if (itb != buckets_.end()) {
++            key_equal const& pred = this->key_eq();
++            p = itb->next;
++            for (; p; p = p->next) {
++              if (pred(x, extractor::extract(p->value()))) {
++                break;
++              }
+             }
+           }
+           return p;
+@@ -2453,11 +2458,13 @@ namespace boost {
+         inline iterator transparent_find(
+           Key const& k, Hash const& h, Pred const& pred) const
+         {
+-          std::size_t const key_hash = h(k);
+-          bucket_iterator itb = buckets_.at(buckets_.position(key_hash));
+-          for (node_pointer p = itb->next; p; p = p->next) {
+-            if (BOOST_LIKELY(pred(k, extractor::extract(p->value())))) {
+-              return iterator(p, itb);
++          if (size_ > 0) {
++            std::size_t const key_hash = h(k);
++            bucket_iterator itb = buckets_.at(buckets_.position(key_hash));
++            for (node_pointer p = itb->next; p; p = p->next) {
++              if (BOOST_LIKELY(pred(k, extractor::extract(p->value())))) {
++                return iterator(p, itb);
++              }
+             }
+           }
+ 
+@@ -2467,11 +2474,13 @@ namespace boost {
+         template <class Key>
+         node_pointer* find_prev(Key const& key, bucket_iterator itb)
+         {
+-          key_equal pred = this->key_eq();
+-          for (node_pointer* pp = boost::addressof(itb->next); *pp;
+-               pp = boost::addressof((*pp)->next)) {
+-            if (pred(key, extractor::extract((*pp)->value()))) {
+-              return pp;
++          if (size_ > 0) {
++            key_equal pred = this->key_eq();
++            for (node_pointer* pp = boost::addressof(itb->next); *pp;
++                pp = boost::addressof((*pp)->next)) {
++              if (pred(key, extractor::extract((*pp)->value()))) {
++                return pp;
++              }
+             }
+           }
+           typedef node_pointer* node_pointer_pointer;
Index: patches/patch-boost_unordered_unordered_map_hpp
===================================================================
RCS file: patches/patch-boost_unordered_unordered_map_hpp
diff -N patches/patch-boost_unordered_unordered_map_hpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-boost_unordered_unordered_map_hpp     29 Aug 2022 19:28:52 
-0000
@@ -0,0 +1,28 @@
+Boost.Unordered containers are not in a valid state after moving
+https://github.com/boostorg/unordered/issues/139
+
+Index: boost/unordered/unordered_map.hpp
+--- boost/unordered/unordered_map.hpp.orig
++++ boost/unordered/unordered_map.hpp
+@@ -2069,6 +2069,10 @@ namespace boost {
+     template <class K, class T, class H, class P, class A>
+     float unordered_map<K, T, H, P, A>::load_factor() const BOOST_NOEXCEPT
+     {
++      if (table_.size_ == 0) {
++        return 0.0f;
++      }
++
+       BOOST_ASSERT(table_.bucket_count() != 0);
+       return static_cast<float>(table_.size_) /
+              static_cast<float>(table_.bucket_count());
+@@ -2506,6 +2510,10 @@ namespace boost {
+     template <class K, class T, class H, class P, class A>
+     float unordered_multimap<K, T, H, P, A>::load_factor() const 
BOOST_NOEXCEPT
+     {
++      if (table_.size_ == 0) {
++        return 0.0f;
++      }
++
+       BOOST_ASSERT(table_.bucket_count() != 0);
+       return static_cast<float>(table_.size_) /
+              static_cast<float>(table_.bucket_count());
Index: patches/patch-boost_unordered_unordered_set_hpp
===================================================================
RCS file: patches/patch-boost_unordered_unordered_set_hpp
diff -N patches/patch-boost_unordered_unordered_set_hpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-boost_unordered_unordered_set_hpp     29 Aug 2022 19:28:52 
-0000
@@ -0,0 +1,28 @@
+Boost.Unordered containers are not in a valid state after moving
+https://github.com/boostorg/unordered/issues/139
+
+Index: boost/unordered/unordered_set.hpp
+--- boost/unordered/unordered_set.hpp.orig
++++ boost/unordered/unordered_set.hpp
+@@ -1586,6 +1586,10 @@ namespace boost {
+     template <class T, class H, class P, class A>
+     float unordered_set<T, H, P, A>::load_factor() const BOOST_NOEXCEPT
+     {
++      if (table_.size_ == 0) {
++        return 0.0f;
++      }
++
+       BOOST_ASSERT(table_.bucket_count() != 0);
+       return static_cast<float>(table_.size_) /
+              static_cast<float>(table_.bucket_count());
+@@ -1986,6 +1990,10 @@ namespace boost {
+     template <class T, class H, class P, class A>
+     float unordered_multiset<T, H, P, A>::load_factor() const BOOST_NOEXCEPT
+     {
++      if (table_.size_ == 0) {
++        return 0.0f;
++      }
++
+       BOOST_ASSERT(table_.bucket_count() != 0);
+       return static_cast<float>(table_.size_) /
+              static_cast<float>(table_.bucket_count());

Reply via email to