Bug 87135 - [C++17] unordered containers violate iterator validity requirements
Summary: [C++17] unordered containers violate iterator validity requirements
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 9.0
: P3 normal
Target Milestone: 9.0
Assignee: François Dumont
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2018-08-29 08:09 UTC by Mitsuru Kariya
Modified: 2018-09-21 20:39 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2018-08-30 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Mitsuru Kariya 2018-08-29 08:09:01 UTC
Please see the sample code below.

=========================== sample code ===========================
#include <iostream>
#include <unordered_set>

template<typename S>
void print(const S& s, typename S::const_iterator& it)
{
  std::cout << "size = " << s.size() << '\n';
  std::cout << "bucket_count = " << s.bucket_count() << '\n';
  std::cout << "load_factor = " << s.load_factor() << '\n';
  std::cout << "max_load_factor = " << s.max_load_factor() << '\n';
  std::cout << "size limit = " << s.bucket_count() * s.max_load_factor() << "\n\n";

  for (std::size_t i = 0; it != s.end() && i < s.size() / 2; ++i, ++it) {
    std::cout << *it << ' ';
  }
  std::cout << "\n\n";
}

int main()
{
  std::unordered_set<int> s;
  const auto max = 10;

  s.reserve(max);
  for (int i = 0; i < max; ++i) {
    s.insert(i);
  }
  auto it = s.cbegin();
  print(s, it);

  s.insert(max);
  print(s, it);
}
=========================== sample code ===========================
=========================== output ===========================
size = 10
bucket_count = 11
load_factor = 0.909091
max_load_factor = 1
size limit = 11

9 8 7 6 5 

size = 11
bucket_count = 23
load_factor = 0.478261
max_load_factor = 1
size limit = 23

4 5 6 7 8 
=========================== output ===========================

cf. https://wandbox.org/permlink/QhPfL6787GV8RYXV

The C++17 standard 26.2.7[unord.req]/p.15 says,

  The insert and emplace members shall not affect the validity of iterators if
  (N+n) <= z * B, where N is the number of elements in the container prior to the
  insert operation, n is the number of elements inserted, B is the container's
  bucket count, and z is the container’s maximum load factor.

So, I think that the sample code above should never rehash.
Comment 1 Jonathan Wakely 2018-08-30 12:55:35 UTC
This changed with https://wg21.link/lwg2156
Comment 2 François Dumont 2018-09-18 20:36:47 UTC
Author: fdumont
Date: Tue Sep 18 20:36:16 2018
New Revision: 264413

URL: https://gcc.gnu.org/viewcvs?rev=264413&root=gcc&view=rev
Log:
2018-09-18  François Dumont  <fdumont@gcc.gnu.org>

	PR libstdc++/87135
	* src/c++11/hashtable_c++0x.cc:
	(_Prime_rehash_policy::_M_next_bkt): Return a prime no smaller than
	requested size, but not necessarily greater.
	(_Prime_rehash_policy::_M_need_rehash): Rehash only if target size is
	strictly greater than next resize threshold.
	* testsuite/23_containers/unordered_map/modifiers/reserve.cc: Adapt test
	to validate that there is no rehash as long as number of insertion is
	lower or equal to the reserved number of elements.

Modified:
    trunk/libstdc++-v3/ChangeLog
    trunk/libstdc++-v3/src/c++11/hashtable_c++0x.cc
    trunk/libstdc++-v3/testsuite/23_containers/unordered_map/modifiers/reserve.cc
Comment 3 François Dumont 2018-09-19 05:32:06 UTC
Rehash policy has been reviewed, rehash will take place only when reserved size is overwhelmed.
Comment 4 François Dumont 2018-09-21 20:39:40 UTC
Author: fdumont
Date: Fri Sep 21 20:39:07 2018
New Revision: 264494

URL: https://gcc.gnu.org/viewcvs?rev=264494&root=gcc&view=rev
Log:
2018-09-21  François Dumont  <fdumont@gcc.gnu.org>

	PR libstdc++/87135
	* src/c++11/hashtable_c++0x.cc (_Prime_rehash_policy::_M_next_bkt):
	Use __builtin_floor to compute _M_next_resize.
	* testsuite/23_containers/unordered_set/hash_policy/71181.cc: Adapt.
	* testsuite/23_containers/unordered_set/hash_policy/prime_rehash.cc:
	Adapt.

Modified:
    trunk/libstdc++-v3/ChangeLog
    trunk/libstdc++-v3/src/c++11/hashtable_c++0x.cc
    trunk/libstdc++-v3/testsuite/23_containers/unordered_set/hash_policy/71181.cc
    trunk/libstdc++-v3/testsuite/23_containers/unordered_set/hash_policy/prime_rehash.cc