Re: [PATCH][Hashtable 5/6] Remove H1/H2 template parameters

2020-08-26 Thread François Dumont via Gcc-patches
Deeply sorry, I indeed didn't sent the patch I wanted to commit. It was 
in 3 commits on my side and it looks like I had miss the last one 
regarding the changes for _ExtractKey.


But moreover I had change the ebo helper index wrongly, I missed the abi 
change here, thanks for fixing it.



On 26/08/20 6:45 pm, Jonathan Wakely wrote:

On 26/08/20 16:58 +0100, Jonathan Wakely wrote:

On 26/08/20 16:55 +0100, Jonathan Wakely wrote:

On 26/08/20 16:30 +0100, Jonathan Wakely wrote:

I'm seeing new FAILures with this:

FAIL: 20_util/function_objects/searchers.cc (test for excess errors)
UNRESOLVED: 20_util/function_objects/searchers.cc compilation 
failed to produce executable

FAIL: experimental/functional/searchers.cc (test for excess errors)
UNRESOLVED: experimental/functional/searchers.cc compilation failed 
to produce executable


It looks like what you committed is not what you sent for review. The
patch sent for review has:

/// Specialization: hash function and range-hashing function, no
/// caching of hash codes.
/// Provides typedef and accessor required by C++ 11.
template
-    struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2,
-  _Default_ranged_hash, false>
+  typename _Hash, typename _RangeHash, typename _Unused>
+    struct _Hash_code_base<_Key, _Value, _ExtractKey, _Hash, 
_RangeHash,

+  _Unused, false>
  : private _Hashtable_ebo_helper<0, _ExtractKey>,
-  private _Hashtable_ebo_helper<1, _H1>,
-  private _Hashtable_ebo_helper<2, _H2>
+  private _Hashtable_ebo_helper<1, _Hash>
  {


But what you committed has:

/// Specialization: hash function and range-hashing function, no
/// caching of hash codes.
/// Provides typedef and accessor required by C++ 11.
template
-    struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2,
-  _Default_ranged_hash, false>
-    : private _Hashtable_ebo_helper<0, _ExtractKey>,
-  private _Hashtable_ebo_helper<1, _H1>,
-  private _Hashtable_ebo_helper<2, _H2>
+  typename _Hash, typename _RangeHash, typename _Unused>
+    struct _Hash_code_base<_Key, _Value, _ExtractKey, _Hash, 
_RangeHash,

+  _Unused, false>
+    : private _Hashtable_ebo_helper<0, _Hash>
  {


Note that you've changed the type of the base class from:

+  private _Hashtable_ebo_helper<1, _Hash>

to

+  private _Hashtable_ebo_helper<0, _Hash>

This causes an ambiguity:

/home/jwakely/src/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/hashtable_policy.h:1706: 
error: 'std::__detail::_Hashtable_ebo_helper<0, test03()::struct>, true>' is an ambiguous base of 
'std::__detail::_Hashtable_baseint>, std::__detail::_Select1st, test03()::, 
test03()::, std::__detail::_Mod_range_hashing, 
std::__detail::_Default_ranged_hash, 
std::__detail::_Hashtable_traits >'


However, what I don't understand is why we are storing that _Hash type
more than once as a base class. That seems wrong (but not something we
can change without ABI impact).


Ah, we're not storing it more than once.

The problem is:

template
struct _Hashtable_base
: public _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, _Hash,
   _Traits::__hash_cached::value>,
  private _Hashtable_ebo_helper<0, _Equal>

This has a base of _Hashtable_ebo_helper<0, _Equal> so it used to
have these bases:

_Hashtable_ebo_helper<0, _ExtractKey>
_Hashtable_ebo_helper<1, _Hash>
_Hashtable_ebo_helper<2, _RangeHash>
_Hashtable_ebo_helper<0, _Equal>

but after your change it has these bases:

_Hashtable_ebo_helper<0, _Hash>
_Hashtable_ebo_helper<0, _Equal>

In the case
where _Equal and _Hash are the same type (which is what I was testing
in the test that fail, because I'm sneaky) that means:

_Hashtable_ebo_helper<0, T>
_Hashtable_ebo_helper<0, T>

which is obviously ambiguous.

I think the _hash_code_base should still use the index 1 for its base
class, i.e. _Hashtable_ebo_helper<1, _Hash>. That way we have these:

_Hashtable_ebo_helper<1, _Hash>
_Hashtable_ebo_helper<0, _Equal>

which works even if they're the same types.


Here's a minimal test:

#include 

struct Evil : std::hash, std::equal_to
{
};

int main()
{
 std::unordered_map h;
 h.key_eq();
}

This fails on current trunk.


Fixed by the attached patch.

Tested powerpc64le-linux, committed to trunk.






Re: [PATCH][Hashtable 5/6] Remove H1/H2 template parameters

2020-08-26 Thread Jonathan Wakely via Gcc-patches

On 26/08/20 16:58 +0100, Jonathan Wakely wrote:

On 26/08/20 16:55 +0100, Jonathan Wakely wrote:

On 26/08/20 16:30 +0100, Jonathan Wakely wrote:

I'm seeing new FAILures with this:

FAIL: 20_util/function_objects/searchers.cc (test for excess errors)
UNRESOLVED: 20_util/function_objects/searchers.cc compilation failed to produce 
executable
FAIL: experimental/functional/searchers.cc (test for excess errors)
UNRESOLVED: experimental/functional/searchers.cc compilation failed to produce 
executable

It looks like what you committed is not what you sent for review. The
patch sent for review has:

/// Specialization: hash function and range-hashing function, no
/// caching of hash codes.
/// Provides typedef and accessor required by C++ 11.
template
-struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2,
-  _Default_ranged_hash, false>
+  typename _Hash, typename _RangeHash, typename _Unused>
+struct _Hash_code_base<_Key, _Value, _ExtractKey, _Hash, _RangeHash,
+  _Unused, false>
  : private _Hashtable_ebo_helper<0, _ExtractKey>,
-  private _Hashtable_ebo_helper<1, _H1>,
-  private _Hashtable_ebo_helper<2, _H2>
+  private _Hashtable_ebo_helper<1, _Hash>
  {


But what you committed has:

/// Specialization: hash function and range-hashing function, no
/// caching of hash codes.
/// Provides typedef and accessor required by C++ 11.
template
-struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2,
-  _Default_ranged_hash, false>
-: private _Hashtable_ebo_helper<0, _ExtractKey>,
-  private _Hashtable_ebo_helper<1, _H1>,
-  private _Hashtable_ebo_helper<2, _H2>
+  typename _Hash, typename _RangeHash, typename _Unused>
+struct _Hash_code_base<_Key, _Value, _ExtractKey, _Hash, _RangeHash,
+  _Unused, false>
+: private _Hashtable_ebo_helper<0, _Hash>
  {


Note that you've changed the type of the base class from:

+  private _Hashtable_ebo_helper<1, _Hash>

to

+  private _Hashtable_ebo_helper<0, _Hash>

This causes an ambiguity:

/home/jwakely/src/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/hashtable_policy.h:1706: error: 
'std::__detail::_Hashtable_ebo_helper<0, test03()::, true>' is an ambiguous base of 
'std::__detail::_Hashtable_base, std::__detail::_Select1st, 
test03()::, test03()::, std::__detail::_Mod_range_hashing, 
std::__detail::_Default_ranged_hash, std::__detail::_Hashtable_traits >'

However, what I don't understand is why we are storing that _Hash type
more than once as a base class. That seems wrong (but not something we
can change without ABI impact).


Ah, we're not storing it more than once.

The problem is:

template
struct _Hashtable_base
: public _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, _Hash,
   _Traits::__hash_cached::value>,
  private _Hashtable_ebo_helper<0, _Equal>

This has a base of _Hashtable_ebo_helper<0, _Equal> so it used to
have these bases:

_Hashtable_ebo_helper<0, _ExtractKey>
_Hashtable_ebo_helper<1, _Hash>
_Hashtable_ebo_helper<2, _RangeHash>
_Hashtable_ebo_helper<0, _Equal>

but after your change it has these bases:

_Hashtable_ebo_helper<0, _Hash>
_Hashtable_ebo_helper<0, _Equal>

In the case
where _Equal and _Hash are the same type (which is what I was testing
in the test that fail, because I'm sneaky) that means:

_Hashtable_ebo_helper<0, T>
_Hashtable_ebo_helper<0, T>

which is obviously ambiguous.

I think the _hash_code_base should still use the index 1 for its base
class, i.e. _Hashtable_ebo_helper<1, _Hash>. That way we have these:

_Hashtable_ebo_helper<1, _Hash>
_Hashtable_ebo_helper<0, _Equal>

which works even if they're the same types.


Here's a minimal test:

#include 

struct Evil : std::hash, std::equal_to
{
};

int main()
{
 std::unordered_map h;
 h.key_eq();
}

This fails on current trunk.


Fixed by the attached patch.

Tested powerpc64le-linux, committed to trunk.


commit 9f9c0549dd42e85e2500ca67cef89dddb142c0c7
Author: Jonathan Wakely 
Date:   Wed Aug 26 17:30:31 2020

libstdc++: Fix regression in hash containers

A recent change altered the layout of EBO-helper base classes, resulting
in an ambiguity when the hash function and equality predicate are the
same type.

This modifies the type of one of the base classes, so that we don't get
two base classes of the same type.

libstdc++-v3/ChangeLog:

* include/bits/hashtable_policy.h (_Hash_code_base): Change
index of _Hashtable_ebo_helper base class.
* testsuite/23_containers/unordered_map/dup_types.cc: New test.

diff --git a/libstdc++-v3/include/bits/hashtable_policy.h b/libstdc++-v3/include/bits/hashtable_policy.h
index 38bd5ae4e81..0109ef86a7b 100644
--- a/libstdc++-v3/include/bits/hashtable_policy.h
+++ b/libstdc++-v3/include/bits/hashtable_policy.h
@@ -1190,10 +1190,10 @@ namespace __detail
 	   

Re: [PATCH][Hashtable 5/6] Remove H1/H2 template parameters

2020-08-26 Thread Jonathan Wakely via Gcc-patches

On 26/08/20 16:55 +0100, Jonathan Wakely wrote:

On 26/08/20 16:30 +0100, Jonathan Wakely wrote:

I'm seeing new FAILures with this:

FAIL: 20_util/function_objects/searchers.cc (test for excess errors)
UNRESOLVED: 20_util/function_objects/searchers.cc compilation failed to produce 
executable
FAIL: experimental/functional/searchers.cc (test for excess errors)
UNRESOLVED: experimental/functional/searchers.cc compilation failed to produce 
executable

It looks like what you committed is not what you sent for review. The
patch sent for review has:

 /// Specialization: hash function and range-hashing function, no
 /// caching of hash codes.
 /// Provides typedef and accessor required by C++ 11.
 template
-struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2,
-  _Default_ranged_hash, false>
+  typename _Hash, typename _RangeHash, typename _Unused>
+struct _Hash_code_base<_Key, _Value, _ExtractKey, _Hash, _RangeHash,
+  _Unused, false>
   : private _Hashtable_ebo_helper<0, _ExtractKey>,
-  private _Hashtable_ebo_helper<1, _H1>,
-  private _Hashtable_ebo_helper<2, _H2>
+  private _Hashtable_ebo_helper<1, _Hash>
   {


But what you committed has:

 /// Specialization: hash function and range-hashing function, no
 /// caching of hash codes.
 /// Provides typedef and accessor required by C++ 11.
 template
-struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2,
-  _Default_ranged_hash, false>
-: private _Hashtable_ebo_helper<0, _ExtractKey>,
-  private _Hashtable_ebo_helper<1, _H1>,
-  private _Hashtable_ebo_helper<2, _H2>
+  typename _Hash, typename _RangeHash, typename _Unused>
+struct _Hash_code_base<_Key, _Value, _ExtractKey, _Hash, _RangeHash,
+  _Unused, false>
+: private _Hashtable_ebo_helper<0, _Hash>
   {


Note that you've changed the type of the base class from:

+  private _Hashtable_ebo_helper<1, _Hash>

to

+  private _Hashtable_ebo_helper<0, _Hash>

This causes an ambiguity:

/home/jwakely/src/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/hashtable_policy.h:1706: error: 
'std::__detail::_Hashtable_ebo_helper<0, test03()::, true>' is an ambiguous base of 
'std::__detail::_Hashtable_base, std::__detail::_Select1st, 
test03()::, test03()::, std::__detail::_Mod_range_hashing, 
std::__detail::_Default_ranged_hash, std::__detail::_Hashtable_traits >'

However, what I don't understand is why we are storing that _Hash type
more than once as a base class. That seems wrong (but not something we
can change without ABI impact).


Ah, we're not storing it more than once.

The problem is:

 template
 struct _Hashtable_base
 : public _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, _Hash,
   _Traits::__hash_cached::value>,
   private _Hashtable_ebo_helper<0, _Equal>

This has a base of _Hashtable_ebo_helper<0, _Equal> so it used to
have these bases:

_Hashtable_ebo_helper<0, _ExtractKey>
_Hashtable_ebo_helper<1, _Hash>
_Hashtable_ebo_helper<2, _RangeHash>
_Hashtable_ebo_helper<0, _Equal>

but after your change it has these bases:

_Hashtable_ebo_helper<0, _Hash>
_Hashtable_ebo_helper<0, _Equal>

In the case
where _Equal and _Hash are the same type (which is what I was testing
in the test that fail, because I'm sneaky) that means:

_Hashtable_ebo_helper<0, T>
_Hashtable_ebo_helper<0, T>

which is obviously ambiguous.

I think the _hash_code_base should still use the index 1 for its base
class, i.e. _Hashtable_ebo_helper<1, _Hash>. That way we have these:

_Hashtable_ebo_helper<1, _Hash>
_Hashtable_ebo_helper<0, _Equal>

which works even if they're the same types.


Here's a minimal test:

#include 

struct Evil : std::hash, std::equal_to
{
};

int main()
{
  std::unordered_map h;
  h.key_eq();
}

This fails on current trunk.



Re: [PATCH][Hashtable 5/6] Remove H1/H2 template parameters

2020-08-26 Thread Jonathan Wakely via Gcc-patches

On 26/08/20 16:30 +0100, Jonathan Wakely wrote:

On 25/08/20 15:30 +0100, Jonathan Wakely wrote:

On 17/08/20 19:13 +0200, François Dumont via Libstdc++ wrote:

Hi

    Here is the new proposal.

    As we can't remove template parameters I simply restore those 
that I tried to pass differently _H2 and _ExtractKey, so 
eventually I only remove usage of _Hash which I renamed in 
_Unused. Maybe I can keep the doc about it in hashtable.h and just 
add a remark saying that it is now unused.


    For _RangeHash, formerly _H2, and _ExtractKey I just stop 
maintaining any storage. When we need those I always use a value 
initialized instance. I kind of prefer the value initialization 
syntax because you can't confuse it with a function call but let 
me know if it is wrong and I should use _ExtractKey() or 
_RangeHash(). I also add some static assertions about those types 
regarding their noexcept qualifications.


    I also included in this patch the few changes left from 
[Hashtable 0/6] which are mostly _M_insert_unique_node and 
_M_insert_multi_node signature cleanup as the key part can be 
extracted from the inserted node.


    Tested under Linux x86_64, ok to commit ?

François

On 06/08/20 11:27 am, Jonathan Wakely wrote:

On 06/08/20 08:35 +0200, François Dumont wrote:

On 17/07/20 1:35 pm, Jonathan Wakely wrote:

I really like the general idea of getting rid of some of the
complexity and not supporting infinite customization. But we can do
that without changing mangled names of the _Hashtable specialiations.



I didn't thought we need to keep abi compatibility for extensions.


These aren't extensions though, they're part of std::unordered_map
etc.

Just because something like _Vector_base is an internal type rather
than something defined in the standard doesn't mean we can just change
its ABI, because that would change the ABI of std::vector. It the same
here.

Changing _Hashtable affects all users of std::unordered_map etc.







diff --git a/libstdc++-v3/include/bits/hashtable.h 
b/libstdc++-v3/include/bits/hashtable.h
index 7b772a475e3..1ba32a3c7e2 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -311,35 +303,37 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
"Cache the hash code or qualify your functors involved"
" in hash code and bucket index computation with noexcept");

-  // When hash codes are cached local iterator inherits from H2 functor
-  // which must then be default constructible.
-  static_assert(__if_hash_cached>::value,
+  // To get bucket index we need _RangeHash not to throw.
+  static_assert(is_nothrow_default_constructible<_RangeHash>::value,
"Functor used to map hash code to bucket index"
-   " must be default constructible");
+   " is nothrow default constructible");


Please phrase this as "must be nothrow default constructible".


+  static_assert(noexcept(
+   std::declval()((std::size_t)0, (std::size_t)0)),
+   "Functor used to map hash code to bucket index is noexcept");


Same here, "must be noexcept".

Otherwise this looks great, thanks. Please push.


I'm seeing new FAILures with this:

FAIL: 20_util/function_objects/searchers.cc (test for excess errors)
UNRESOLVED: 20_util/function_objects/searchers.cc compilation failed to produce 
executable
FAIL: experimental/functional/searchers.cc (test for excess errors)
UNRESOLVED: experimental/functional/searchers.cc compilation failed to produce 
executable

It looks like what you committed is not what you sent for review. The
patch sent for review has:

  /// Specialization: hash function and range-hashing function, no
  /// caching of hash codes.
  /// Provides typedef and accessor required by C++ 11.
  template
-struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2,
-  _Default_ranged_hash, false>
+  typename _Hash, typename _RangeHash, typename _Unused>
+struct _Hash_code_base<_Key, _Value, _ExtractKey, _Hash, _RangeHash,
+  _Unused, false>
: private _Hashtable_ebo_helper<0, _ExtractKey>,
-  private _Hashtable_ebo_helper<1, _H1>,
-  private _Hashtable_ebo_helper<2, _H2>
+  private _Hashtable_ebo_helper<1, _Hash>
{


But what you committed has:

  /// Specialization: hash function and range-hashing function, no
  /// caching of hash codes.
  /// Provides typedef and accessor required by C++ 11.
  template
-struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2,
-  _Default_ranged_hash, false>
-: private _Hashtable_ebo_helper<0, _ExtractKey>,
-  private _Hashtable_ebo_helper<1, _H1>,
-  private _Hashtable_ebo_helper<2, _H2>
+  typename _Hash, typename _RangeHash, typename _Unused>
+struct _Hash_code_base<_Key, _Value, _ExtractKey, _Hash, _RangeHash,
+  _Unused, false>

Re: [PATCH][Hashtable 5/6] Remove H1/H2 template parameters

2020-08-26 Thread Jonathan Wakely via Gcc-patches

On 25/08/20 15:30 +0100, Jonathan Wakely wrote:

On 17/08/20 19:13 +0200, François Dumont via Libstdc++ wrote:

Hi

    Here is the new proposal.

    As we can't remove template parameters I simply restore those 
that I tried to pass differently _H2 and _ExtractKey, so eventually 
I only remove usage of _Hash which I renamed in _Unused. Maybe I can 
keep the doc about it in hashtable.h and just add a remark saying 
that it is now unused.


    For _RangeHash, formerly _H2, and _ExtractKey I just stop 
maintaining any storage. When we need those I always use a value 
initialized instance. I kind of prefer the value initialization 
syntax because you can't confuse it with a function call but let me 
know if it is wrong and I should use _ExtractKey() or _RangeHash(). 
I also add some static assertions about those types regarding their 
noexcept qualifications.


    I also included in this patch the few changes left from 
[Hashtable 0/6] which are mostly _M_insert_unique_node and 
_M_insert_multi_node signature cleanup as the key part can be 
extracted from the inserted node.


    Tested under Linux x86_64, ok to commit ?

François

On 06/08/20 11:27 am, Jonathan Wakely wrote:

On 06/08/20 08:35 +0200, François Dumont wrote:

On 17/07/20 1:35 pm, Jonathan Wakely wrote:

I really like the general idea of getting rid of some of the
complexity and not supporting infinite customization. But we can do
that without changing mangled names of the _Hashtable specialiations.



I didn't thought we need to keep abi compatibility for extensions.


These aren't extensions though, they're part of std::unordered_map
etc.

Just because something like _Vector_base is an internal type rather
than something defined in the standard doesn't mean we can just change
its ABI, because that would change the ABI of std::vector. It the same
here.

Changing _Hashtable affects all users of std::unordered_map etc.







diff --git a/libstdc++-v3/include/bits/hashtable.h 
b/libstdc++-v3/include/bits/hashtable.h
index 7b772a475e3..1ba32a3c7e2 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -311,35 +303,37 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
"Cache the hash code or qualify your functors involved"
" in hash code and bucket index computation with noexcept");

-  // When hash codes are cached local iterator inherits from H2 functor
-  // which must then be default constructible.
-  static_assert(__if_hash_cached>::value,
+  // To get bucket index we need _RangeHash not to throw.
+  static_assert(is_nothrow_default_constructible<_RangeHash>::value,
"Functor used to map hash code to bucket index"
-   " must be default constructible");
+   " is nothrow default constructible");


Please phrase this as "must be nothrow default constructible".


+  static_assert(noexcept(
+   std::declval()((std::size_t)0, (std::size_t)0)),
+   "Functor used to map hash code to bucket index is noexcept");


Same here, "must be noexcept".

Otherwise this looks great, thanks. Please push.


I'm seeing new FAILures with this:

FAIL: 20_util/function_objects/searchers.cc (test for excess errors)
UNRESOLVED: 20_util/function_objects/searchers.cc compilation failed to produce 
executable
FAIL: experimental/functional/searchers.cc (test for excess errors)
UNRESOLVED: experimental/functional/searchers.cc compilation failed to produce 
executable

It looks like what you committed is not what you sent for review. The
patch sent for review has:

   /// Specialization: hash function and range-hashing function, no
   /// caching of hash codes.
   /// Provides typedef and accessor required by C++ 11.
   template
-struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2,
-  _Default_ranged_hash, false>
+  typename _Hash, typename _RangeHash, typename _Unused>
+struct _Hash_code_base<_Key, _Value, _ExtractKey, _Hash, _RangeHash,
+  _Unused, false>
 : private _Hashtable_ebo_helper<0, _ExtractKey>,
-  private _Hashtable_ebo_helper<1, _H1>,
-  private _Hashtable_ebo_helper<2, _H2>
+  private _Hashtable_ebo_helper<1, _Hash>
 {


But what you committed has:

   /// Specialization: hash function and range-hashing function, no
   /// caching of hash codes.
   /// Provides typedef and accessor required by C++ 11.
   template
-struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2,
-  _Default_ranged_hash, false>
-: private _Hashtable_ebo_helper<0, _ExtractKey>,
-  private _Hashtable_ebo_helper<1, _H1>,
-  private _Hashtable_ebo_helper<2, _H2>
+  typename _Hash, typename _RangeHash, typename _Unused>
+struct _Hash_code_base<_Key, _Value, _ExtractKey, _Hash, _RangeHash,
+  _Unused, false>
+: private _Hashtable_ebo_helper<0, 

Re: [PATCH][Hashtable 5/6] Remove H1/H2 template parameters

2020-08-25 Thread Jonathan Wakely via Gcc-patches

On 17/08/20 19:13 +0200, François Dumont via Libstdc++ wrote:

Hi

    Here is the new proposal.

    As we can't remove template parameters I simply restore those that 
I tried to pass differently _H2 and _ExtractKey, so eventually I only 
remove usage of _Hash which I renamed in _Unused. Maybe I can keep the 
doc about it in hashtable.h and just add a remark saying that it is 
now unused.


    For _RangeHash, formerly _H2, and _ExtractKey I just stop 
maintaining any storage. When we need those I always use a value 
initialized instance. I kind of prefer the value initialization syntax 
because you can't confuse it with a function call but let me know if 
it is wrong and I should use _ExtractKey() or _RangeHash(). I also add 
some static assertions about those types regarding their noexcept 
qualifications.


    I also included in this patch the few changes left from [Hashtable 
0/6] which are mostly _M_insert_unique_node and _M_insert_multi_node 
signature cleanup as the key part can be extracted from the inserted 
node.


    Tested under Linux x86_64, ok to commit ?

François

On 06/08/20 11:27 am, Jonathan Wakely wrote:

On 06/08/20 08:35 +0200, François Dumont wrote:

On 17/07/20 1:35 pm, Jonathan Wakely wrote:

I really like the general idea of getting rid of some of the
complexity and not supporting infinite customization. But we can do
that without changing mangled names of the _Hashtable specialiations.



I didn't thought we need to keep abi compatibility for extensions.


These aren't extensions though, they're part of std::unordered_map
etc.

Just because something like _Vector_base is an internal type rather
than something defined in the standard doesn't mean we can just change
its ABI, because that would change the ABI of std::vector. It the same
here.

Changing _Hashtable affects all users of std::unordered_map etc.







diff --git a/libstdc++-v3/include/bits/hashtable.h 
b/libstdc++-v3/include/bits/hashtable.h
index 7b772a475e3..1ba32a3c7e2 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -311,35 +303,37 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
"Cache the hash code or qualify your functors involved"
" in hash code and bucket index computation with noexcept");

-  // When hash codes are cached local iterator inherits from H2 functor
-  // which must then be default constructible.
-  static_assert(__if_hash_cached>::value,
+  // To get bucket index we need _RangeHash not to throw.
+  static_assert(is_nothrow_default_constructible<_RangeHash>::value,
"Functor used to map hash code to bucket index"
-   " must be default constructible");
+   " is nothrow default constructible");


Please phrase this as "must be nothrow default constructible".


+  static_assert(noexcept(
+   std::declval()((std::size_t)0, (std::size_t)0)),
+   "Functor used to map hash code to bucket index is noexcept");


Same here, "must be noexcept".

Otherwise this looks great, thanks. Please push.




Re: [PATCH][Hashtable 5/6] Remove H1/H2 template parameters

2020-08-17 Thread François Dumont via Gcc-patches

Hi

    Here is the new proposal.

    As we can't remove template parameters I simply restore those that 
I tried to pass differently _H2 and _ExtractKey, so eventually I only 
remove usage of _Hash which I renamed in _Unused. Maybe I can keep the 
doc about it in hashtable.h and just add a remark saying that it is now 
unused.


    For _RangeHash, formerly _H2, and _ExtractKey I just stop 
maintaining any storage. When we need those I always use a value 
initialized instance. I kind of prefer the value initialization syntax 
because you can't confuse it with a function call but let me know if it 
is wrong and I should use _ExtractKey() or _RangeHash(). I also add some 
static assertions about those types regarding their noexcept qualifications.


    I also included in this patch the few changes left from [Hashtable 
0/6] which are mostly _M_insert_unique_node and _M_insert_multi_node 
signature cleanup as the key part can be extracted from the inserted node.


    Tested under Linux x86_64, ok to commit ?

François

On 06/08/20 11:27 am, Jonathan Wakely wrote:

On 06/08/20 08:35 +0200, François Dumont wrote:

On 17/07/20 1:35 pm, Jonathan Wakely wrote:

I really like the general idea of getting rid of some of the
complexity and not supporting infinite customization. But we can do
that without changing mangled names of the _Hashtable specialiations.



I didn't thought we need to keep abi compatibility for extensions.


These aren't extensions though, they're part of std::unordered_map
etc.

Just because something like _Vector_base is an internal type rather
than something defined in the standard doesn't mean we can just change
its ABI, because that would change the ABI of std::vector. It the same
here.

Changing _Hashtable affects all users of std::unordered_map etc.




diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h
index 7b772a475e3..1ba32a3c7e2 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -69,21 +69,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*  and returns a bool-like value that is true if the two objects
*  are considered equal.
*
-   *  @tparam _H1  The hash function. A unary function object with
+   *  @tparam _Hash  The hash function. A unary function object with
*  argument type _Key and result type size_t. Return values should
*  be distributed over the entire range [0, numeric_limits:::max()].
*
-   *  @tparam _H2  The range-hashing function (in the terminology of
+   *  @tparam _RangeHash  The range-hashing function (in the terminology of
*  Tavori and Dreizin).  A binary function object whose argument
*  types and result type are all size_t.  Given arguments r and N,
*  the return value is in the range [0, N).
*
-   *  @tparam _Hash  The ranged hash function (Tavori and Dreizin). A
-   *  binary function whose argument types are _Key and size_t and
-   *  whose result type is size_t.  Given arguments k and N, the
-   *  return value is in the range [0, N).  Default: hash(k, N) =
-   *  h2(h1(k), N).  If _Hash is anything other than the default, _H1
-   *  and _H2 are ignored.
+   *  @tparam _Unused  Not used.
*
*  @tparam _RehashPolicy  Policy class with three members, all of
*  which govern the bucket count. _M_next_bkt(n) returns a bucket
@@ -91,9 +86,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*  bucket count appropriate for an element count of n.
*  _M_need_rehash(n_bkt, n_elt, n_ins) determines whether, if the
*  current bucket count is n_bkt and the current element count is
-   *  n_elt, we need to increase the bucket count.  If so, returns
-   *  make_pair(true, n), where n is the new bucket count.  If not,
-   *  returns make_pair(false, )
+   *  n_elt, we need to increase the bucket count for n_ins insertions.
+   *  If so, returns make_pair(true, n), where n is the new bucket count. If
+   *  not, returns make_pair(false, )
*
*  @tparam _Traits  Compile-time class with three boolean
*  std::integral_constant members:  __cache_hash_code, __constant_iterators,
@@ -168,19 +163,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*/
   template
 class _Hashtable
 : public __detail::_Hashtable_base<_Key, _Value, _ExtractKey, _Equal,
-   _H1, _H2, _Hash, _Traits>,
+   _Hash, _RangeHash, _Unused, _Traits>,
   public __detail::_Map_base<_Key, _Value, _Alloc, _ExtractKey, _Equal,
- _H1, _H2, _Hash, _RehashPolicy, _Traits>,
+ _Hash, _RangeHash, _Unused,
+ _RehashPolicy, _Traits>,
   public __detail::_Insert<_Key, _Value, _Alloc, _ExtractKey, _Equal,
-			   _H1, _H2, _Hash, _RehashPolicy, _Traits>,
+			   _Hash, _RangeHash, _Unused,
+			   _RehashPolicy, _Traits>,
   public __detail::_Rehash_base<_Key, _Value, _Alloc, _ExtractKey, _Equal,
-_H1, _H2, _Hash, _RehashPolicy, _Traits>,
+_Hash, _RangeHash, _Unused,
+_RehashPolicy, _Traits>,
   public 

Re: [PATCH][Hashtable 5/6] Remove H1/H2 template parameters

2020-08-06 Thread Jonathan Wakely via Gcc-patches

On 06/08/20 08:35 +0200, François Dumont wrote:

On 17/07/20 1:35 pm, Jonathan Wakely wrote:

I really like the general idea of getting rid of some of the
complexity and not supporting infinite customization. But we can do
that without changing mangled names of the _Hashtable specialiations.



I didn't thought we need to keep abi compatibility for extensions.


These aren't extensions though, they're part of std::unordered_map
etc.

Just because something like _Vector_base is an internal type rather
than something defined in the standard doesn't mean we can just change
its ABI, because that would change the ABI of std::vector. It the same
here.

Changing _Hashtable affects all users of std::unordered_map etc.




Re: [PATCH][Hashtable 5/6] Remove H1/H2 template parameters

2020-08-06 Thread François Dumont via Gcc-patches

On 17/07/20 1:35 pm, Jonathan Wakely wrote:

On 19/12/19 20:22 +0100, François Dumont wrote:

Because of this change printers.py has to be updated too.

François


On 11/17/19 10:15 PM, François Dumont wrote:
H1 used to be a reference to the user Hash, now _Hashtable and 
unordered types agree on the same Hash type which is more intuitive.


I also chose to not support anymore a stateful ranged hash functor. 
We only use _Mod_range_hashing and _Mask_range_hashing.


Thanks to this simplification _M_bucket_index can also be simplified.

    * include/bits/hashtable_policy.h (_Hashtable<>): Remove _H1 
and _H2

    template parameters.
    (_Hastable_base<>): Likewise.
    (_Default_ranged_hash): Remove.
    (_Prime_rehash_policy::__ranged_hash): New.
    (_Power2_rehash_policy::__ranged_hash): New.
    (_Map_base<>): Remove _H1 and _H2 template parameters.
    (_Insert_base<>): Likewise.
    (_Insert<>): Likewise.
    (_Rehash_base<>): Likewise.
    (_Local_iterator_base<>): Remove _H1 and _H2 template 
parameters and add

    _RangedHash.
    (_Hash_code_base<>): Likewise.
    (_Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, _Hash,
    __hash_not_cached_t>): Remove.
    (_Hash_code_base<>::_M_bucket_index(const _Key&, __hash_code, 
size_t)):

    Replace by...
    (_Hash_code_base<>::_M_bucket_index(__hash_code, size_t)): 
...this.

    (_Local_iterator<>): Remove _H1 and _H2 template parameters.
    (_Local_const_iterator<>): Likewise.
    (_Equality<>): Likewise.
    * include/bits/hashtable.h (_Hashtable<>): Remove _H1 and _H2 
template

    parameters.
    * include/bits/node_handle.h: Adapt.
    * include/bits/unordered_map.h: Adapt.
    * include/bits/unordered_set.h: Adapt.
    * testsuite/23_containers/unordered_set/hash_policy/26132.cc: 
Adapt.
    * testsuite/23_containers/unordered_set/hash_policy/71181.cc: 
Adapt.
    * 
testsuite/23_containers/unordered_set/hash_policy/load_factor.cc:

    Adapt.
    * 
testsuite/23_containers/unordered_set/hash_policy/rehash.cc: Adapt.
    * 
testsuite/23_containers/unordered_set/insert/hash_policy.cc: Adapt.
    * 
testsuite/23_containers/unordered_set/max_load_factor/robustness.cc:

    Adapt.
    * testsuite/performance/23_containers/insert/54075.cc: Adapt.
    * testsuite/performance/23_containers/insert_erase/41975.cc: 
Adapt.

    * testsuite/performance/23_containers/insert_erase/
    unordered_small_size.cc: Adapt.

Tested under Linux x86_64.

François






diff --git a/libstdc++-v3/include/bits/hashtable.h 
b/libstdc++-v3/include/bits/hashtable.h

index 41be821782d..9dadc62e328 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -69,31 +69,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   *  and returns a bool-like value that is true if the two objects
   *  are considered equal.
   *
-   *  @tparam _H1  The hash function. A unary function object with
+   *  @tparam _Hash  The hash function. A unary function object with


Renaming this to _Hash is great, that makes the code much easier to
understand for a casual reader (like me every time I have to remember
how our hash tables work).

It makes much more sense for the _Hash parameter of unordered_set and
the _Hash parameter of _Hashtable to be the same thing!


   *  argument type _Key and result type size_t. Return values should
   *  be distributed over the entire range [0, 
numeric_limits:::max()].

   *
-   *  @tparam _H2  The range-hashing function (in the terminology of
-   *  Tavori and Dreizin).  A binary function object whose argument
-   *  types and result type are all size_t.  Given arguments r and N,
-   *  the return value is in the range [0, N).
-   *
-   *  @tparam _Hash  The ranged hash function (Tavori and Dreizin). A
-   *  binary function whose argument types are _Key and size_t and
-   *  whose result type is size_t.  Given arguments k and N, the
-   *  return value is in the range [0, N).  Default: hash(k, N) =
-   *  h2(h1(k), N).  If _Hash is anything other than the default, _H1
-   *  and _H2 are ignored.


But I would prefer to keep these parameters, and just rename them to
_Unused1 and _Unused2 or something like that. Maybe _U1 and _U2.

You can still get rid of them as constructor parameters and get rid of
the base classes using those types. Just keep them in the template
argument lists, so that we keep generating the same mangled names for
specializations of _Hashtable.

That way you don't need to change printers.py (which is good, because
that change to printers.py is not OK anyway - it would make it
impossible to debug code built with older versions of GCC, because the
printers would only support the new layout - we need to support
debugging programs that were not all built by the same version of
GCC).


@@ -168,19 +155,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   */
  template
+   typename _Hash, typename 

Re: [PATCH][Hashtable 5/6] Remove H1/H2 template parameters

2020-07-17 Thread Jonathan Wakely via Gcc-patches

On 19/12/19 20:22 +0100, François Dumont wrote:

Because of this change printers.py has to be updated too.

François


On 11/17/19 10:15 PM, François Dumont wrote:
H1 used to be a reference to the user Hash, now _Hashtable and 
unordered types agree on the same Hash type which is more intuitive.


I also chose to not support anymore a stateful ranged hash functor. 
We only use _Mod_range_hashing and _Mask_range_hashing.


Thanks to this simplification _M_bucket_index can also be simplified.

    * include/bits/hashtable_policy.h (_Hashtable<>): Remove _H1 and _H2
    template parameters.
    (_Hastable_base<>): Likewise.
    (_Default_ranged_hash): Remove.
    (_Prime_rehash_policy::__ranged_hash): New.
    (_Power2_rehash_policy::__ranged_hash): New.
    (_Map_base<>): Remove _H1 and _H2 template parameters.
    (_Insert_base<>): Likewise.
    (_Insert<>): Likewise.
    (_Rehash_base<>): Likewise.
    (_Local_iterator_base<>): Remove _H1 and _H2 template parameters 
and add

    _RangedHash.
    (_Hash_code_base<>): Likewise.
    (_Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, _Hash,
    __hash_not_cached_t>): Remove.
    (_Hash_code_base<>::_M_bucket_index(const _Key&, __hash_code, 
size_t)):

    Replace by...
    (_Hash_code_base<>::_M_bucket_index(__hash_code, size_t)): ...this.
    (_Local_iterator<>): Remove _H1 and _H2 template parameters.
    (_Local_const_iterator<>): Likewise.
    (_Equality<>): Likewise.
    * include/bits/hashtable.h (_Hashtable<>): Remove _H1 and _H2 
template

    parameters.
    * include/bits/node_handle.h: Adapt.
    * include/bits/unordered_map.h: Adapt.
    * include/bits/unordered_set.h: Adapt.
    * testsuite/23_containers/unordered_set/hash_policy/26132.cc: Adapt.
    * testsuite/23_containers/unordered_set/hash_policy/71181.cc: Adapt.
    * testsuite/23_containers/unordered_set/hash_policy/load_factor.cc:
    Adapt.
    * testsuite/23_containers/unordered_set/hash_policy/rehash.cc: Adapt.
    * testsuite/23_containers/unordered_set/insert/hash_policy.cc: Adapt.
    * 
testsuite/23_containers/unordered_set/max_load_factor/robustness.cc:

    Adapt.
    * testsuite/performance/23_containers/insert/54075.cc: Adapt.
    * testsuite/performance/23_containers/insert_erase/41975.cc: Adapt.
    * testsuite/performance/23_containers/insert_erase/
    unordered_small_size.cc: Adapt.

Tested under Linux x86_64.

François







diff --git a/libstdc++-v3/include/bits/hashtable.h 
b/libstdc++-v3/include/bits/hashtable.h
index 41be821782d..9dadc62e328 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -69,31 +69,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   *  and returns a bool-like value that is true if the two objects
   *  are considered equal.
   *
-   *  @tparam _H1  The hash function. A unary function object with
+   *  @tparam _Hash  The hash function. A unary function object with


Renaming this to _Hash is great, that makes the code much easier to
understand for a casual reader (like me every time I have to remember
how our hash tables work).

It makes much more sense for the _Hash parameter of unordered_set and
the _Hash parameter of _Hashtable to be the same thing!


   *  argument type _Key and result type size_t. Return values should
   *  be distributed over the entire range [0, numeric_limits:::max()].
   *
-   *  @tparam _H2  The range-hashing function (in the terminology of
-   *  Tavori and Dreizin).  A binary function object whose argument
-   *  types and result type are all size_t.  Given arguments r and N,
-   *  the return value is in the range [0, N).
-   *
-   *  @tparam _Hash  The ranged hash function (Tavori and Dreizin). A
-   *  binary function whose argument types are _Key and size_t and
-   *  whose result type is size_t.  Given arguments k and N, the
-   *  return value is in the range [0, N).  Default: hash(k, N) =
-   *  h2(h1(k), N).  If _Hash is anything other than the default, _H1
-   *  and _H2 are ignored.


But I would prefer to keep these parameters, and just rename them to
_Unused1 and _Unused2 or something like that. Maybe _U1 and _U2.

You can still get rid of them as constructor parameters and get rid of
the base classes using those types. Just keep them in the template
argument lists, so that we keep generating the same mangled names for
specializations of _Hashtable.

That way you don't need to change printers.py (which is good, because
that change to printers.py is not OK anyway - it would make it
impossible to debug code built with older versions of GCC, because the
printers would only support the new layout - we need to support
debugging programs that were not all built by the same version of
GCC).


@@ -168,19 +155,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   */
  template
+  typename _Hash, typename _RehashPolicy, typename _Traits>


So to be clear, what 

Re: [PATCH][Hashtable 5/6] Remove H1/H2 template parameters

2020-07-17 Thread Jonathan Wakely via Gcc-patches

On 19/11/19 00:10 +0200, Ville Voutilainen wrote:

On Mon, 18 Nov 2019 at 23:41, François Dumont  wrote:

>   Also, is
> this ABI-compatible
> for our unordered containers?
>
IMHO, yes it is.

In hashtable_policy.h _H1 was the user hash which I renamed in _Hash,
the same template name that for unordered containers.

_H2 was always _Mod_range_hashing and previous _Hash always
_Default_ranged_hash, both stateless types. Only _H1 and _H2 were stored
in _Hash_code_base for instance. _H1 is still as _Hash and _H2 was just
empty and moreover stored last so removing it has no impact.


Right, and as I understood the code, it's all empty base objects
anyway, so it boils down to whether
a set of empty bases can change without causing an ABI break, and I
don't think there's an ABI
problem here because the actual _Hashtable is stored as a member of
various containers, and its
size doesn't change, and based on what you wrote, with which my
code-reading agrees, the behaviour
doesn't change either. So the patch seems okay to me.


There's no guarantee that a program-defined hash object is actually
empty.



Re: [PATCH][Hashtable 5/6] Remove H1/H2 template parameters

2019-12-19 Thread François Dumont

Because of this change printers.py has to be updated too.

François


On 11/17/19 10:15 PM, François Dumont wrote:
H1 used to be a reference to the user Hash, now _Hashtable and 
unordered types agree on the same Hash type which is more intuitive.


I also chose to not support anymore a stateful ranged hash functor. We 
only use _Mod_range_hashing and _Mask_range_hashing.


Thanks to this simplification _M_bucket_index can also be simplified.

    * include/bits/hashtable_policy.h (_Hashtable<>): Remove _H1 and _H2
    template parameters.
    (_Hastable_base<>): Likewise.
    (_Default_ranged_hash): Remove.
    (_Prime_rehash_policy::__ranged_hash): New.
    (_Power2_rehash_policy::__ranged_hash): New.
    (_Map_base<>): Remove _H1 and _H2 template parameters.
    (_Insert_base<>): Likewise.
    (_Insert<>): Likewise.
    (_Rehash_base<>): Likewise.
    (_Local_iterator_base<>): Remove _H1 and _H2 template parameters 
and add

    _RangedHash.
    (_Hash_code_base<>): Likewise.
    (_Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, _Hash,
    __hash_not_cached_t>): Remove.
    (_Hash_code_base<>::_M_bucket_index(const _Key&, __hash_code, 
size_t)):

    Replace by...
    (_Hash_code_base<>::_M_bucket_index(__hash_code, size_t)): ...this.
    (_Local_iterator<>): Remove _H1 and _H2 template parameters.
    (_Local_const_iterator<>): Likewise.
    (_Equality<>): Likewise.
    * include/bits/hashtable.h (_Hashtable<>): Remove _H1 and _H2 
template

    parameters.
    * include/bits/node_handle.h: Adapt.
    * include/bits/unordered_map.h: Adapt.
    * include/bits/unordered_set.h: Adapt.
    * testsuite/23_containers/unordered_set/hash_policy/26132.cc: Adapt.
    * testsuite/23_containers/unordered_set/hash_policy/71181.cc: Adapt.
    * testsuite/23_containers/unordered_set/hash_policy/load_factor.cc:
    Adapt.
    * testsuite/23_containers/unordered_set/hash_policy/rehash.cc: Adapt.
    * testsuite/23_containers/unordered_set/insert/hash_policy.cc: Adapt.
    * 
testsuite/23_containers/unordered_set/max_load_factor/robustness.cc:

    Adapt.
    * testsuite/performance/23_containers/insert/54075.cc: Adapt.
    * testsuite/performance/23_containers/insert_erase/41975.cc: Adapt.
    * testsuite/performance/23_containers/insert_erase/
    unordered_small_size.cc: Adapt.

Tested under Linux x86_64.

François




diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h
index 41be821782d..9dadc62e328 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -69,31 +69,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*  and returns a bool-like value that is true if the two objects
*  are considered equal.
*
-   *  @tparam _H1  The hash function. A unary function object with
+   *  @tparam _Hash  The hash function. A unary function object with
*  argument type _Key and result type size_t. Return values should
*  be distributed over the entire range [0, numeric_limits:::max()].
*
-   *  @tparam _H2  The range-hashing function (in the terminology of
-   *  Tavori and Dreizin).  A binary function object whose argument
-   *  types and result type are all size_t.  Given arguments r and N,
-   *  the return value is in the range [0, N).
-   *
-   *  @tparam _Hash  The ranged hash function (Tavori and Dreizin). A
-   *  binary function whose argument types are _Key and size_t and
-   *  whose result type is size_t.  Given arguments k and N, the
-   *  return value is in the range [0, N).  Default: hash(k, N) =
-   *  h2(h1(k), N).  If _Hash is anything other than the default, _H1
-   *  and _H2 are ignored.
-   *
-   *  @tparam _RehashPolicy  Policy class with three members, all of
-   *  which govern the bucket count. _M_next_bkt(n) returns a bucket
-   *  count no smaller than n.  _M_bkt_for_elements(n) returns a
-   *  bucket count appropriate for an element count of n.
-   *  _M_need_rehash(n_bkt, n_elt, n_ins) determines whether, if the
-   *  current bucket count is n_bkt and the current element count is
-   *  n_elt, we need to increase the bucket count.  If so, returns
-   *  make_pair(true, n), where n is the new bucket count.  If not,
-   *  returns make_pair(false, )
+   *  @tparam _RehashPolicy  Policy class with three members, all of which
+   *  govern the bucket count. _M_next_bkt(n) returns a bucket count no smaller
+   *  than n. _M_bkt_for_elements(n) returns a bucket count appropriate for an
+   *  element count of n. _M_need_rehash(n_bkt, n_elt, n_ins) determines
+   *  whether, if the current bucket count is n_bkt and the current element
+   *  count is n_elt, we need to increase the bucket count for n_ins insertions.
+   *  If so, returns make_pair(true, n), where n is the new bucket count. If
+   *  not, returns make_pair(false, )
*
*  @tparam _Traits  Compile-time class with three boolean
*  std::integral_constant members:  __cache_hash_code, __constant_iterators,
@@ -168,19 +155,19 @@ 

Re: [PATCH][Hashtable 5/6] Remove H1/H2 template parameters

2019-11-18 Thread Ville Voutilainen
On Mon, 18 Nov 2019 at 23:41, François Dumont  wrote:
> >   Also, is
> > this ABI-compatible
> > for our unordered containers?
> >
> IMHO, yes it is.
>
> In hashtable_policy.h _H1 was the user hash which I renamed in _Hash,
> the same template name that for unordered containers.
>
> _H2 was always _Mod_range_hashing and previous _Hash always
> _Default_ranged_hash, both stateless types. Only _H1 and _H2 were stored
> in _Hash_code_base for instance. _H1 is still as _Hash and _H2 was just
> empty and moreover stored last so removing it has no impact.

Right, and as I understood the code, it's all empty base objects
anyway, so it boils down to whether
a set of empty bases can change without causing an ABI break, and I
don't think there's an ABI
problem here because the actual _Hashtable is stored as a member of
various containers, and its
size doesn't change, and based on what you wrote, with which my
code-reading agrees, the behaviour
doesn't change either. So the patch seems okay to me.


Re: [PATCH][Hashtable 5/6] Remove H1/H2 template parameters

2019-11-18 Thread François Dumont

On 11/17/19 11:21 PM, Ville Voutilainen wrote:

On Sun, 17 Nov 2019 at 23:15, François Dumont  wrote:

H1 used to be a reference to the user Hash, now _Hashtable and unordered
types agree on the same Hash type which is more intuitive.

I also chose to not support anymore a stateful ranged hash functor. We
only use _Mod_range_hashing and _Mask_range_hashing.

Thanks to this simplification _M_bucket_index can also be simplified.

Do we know whether there are existing users that this breaks?


That's the problem with this kind of extension, we don't know.

However we never get any report neither about potential users. And I 
remember that I fixed some years ago a bug that users would have 
reported much sooner if there have been users. But it was some years ago.



  Also, is
this ABI-compatible
for our unordered containers?


IMHO, yes it is.

In hashtable_policy.h _H1 was the user hash which I renamed in _Hash, 
the same template name that for unordered containers.


_H2 was always _Mod_range_hashing and previous _Hash always 
_Default_ranged_hash, both stateless types. Only _H1 and _H2 were stored 
in _Hash_code_base for instance. _H1 is still as _Hash and _H2 was just 
empty and moreover stored last so removing it has no impact.


François



Re: [PATCH][Hashtable 5/6] Remove H1/H2 template parameters

2019-11-17 Thread Ville Voutilainen
On Sun, 17 Nov 2019 at 23:15, François Dumont  wrote:
>
> H1 used to be a reference to the user Hash, now _Hashtable and unordered
> types agree on the same Hash type which is more intuitive.
>
> I also chose to not support anymore a stateful ranged hash functor. We
> only use _Mod_range_hashing and _Mask_range_hashing.
>
> Thanks to this simplification _M_bucket_index can also be simplified.

Do we know whether there are existing users that this breaks? Also, is
this ABI-compatible
for our unordered containers?


[PATCH][Hashtable 5/6] Remove H1/H2 template parameters

2019-11-17 Thread François Dumont
H1 used to be a reference to the user Hash, now _Hashtable and unordered 
types agree on the same Hash type which is more intuitive.


I also chose to not support anymore a stateful ranged hash functor. We 
only use _Mod_range_hashing and _Mask_range_hashing.


Thanks to this simplification _M_bucket_index can also be simplified.

    * include/bits/hashtable_policy.h (_Hashtable<>): Remove _H1 and _H2
    template parameters.
    (_Hastable_base<>): Likewise.
    (_Default_ranged_hash): Remove.
    (_Prime_rehash_policy::__ranged_hash): New.
    (_Power2_rehash_policy::__ranged_hash): New.
    (_Map_base<>): Remove _H1 and _H2 template parameters.
    (_Insert_base<>): Likewise.
    (_Insert<>): Likewise.
    (_Rehash_base<>): Likewise.
    (_Local_iterator_base<>): Remove _H1 and _H2 template parameters 
and add

    _RangedHash.
    (_Hash_code_base<>): Likewise.
    (_Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, _Hash,
    __hash_not_cached_t>): Remove.
    (_Hash_code_base<>::_M_bucket_index(const _Key&, __hash_code, size_t)):
    Replace by...
    (_Hash_code_base<>::_M_bucket_index(__hash_code, size_t)): ...this.
    (_Local_iterator<>): Remove _H1 and _H2 template parameters.
    (_Local_const_iterator<>): Likewise.
    (_Equality<>): Likewise.
    * include/bits/hashtable.h (_Hashtable<>): Remove _H1 and _H2 template
    parameters.
    * include/bits/node_handle.h: Adapt.
    * include/bits/unordered_map.h: Adapt.
    * include/bits/unordered_set.h: Adapt.
    * testsuite/23_containers/unordered_set/hash_policy/26132.cc: Adapt.
    * testsuite/23_containers/unordered_set/hash_policy/71181.cc: Adapt.
    * testsuite/23_containers/unordered_set/hash_policy/load_factor.cc:
    Adapt.
    * testsuite/23_containers/unordered_set/hash_policy/rehash.cc: Adapt.
    * testsuite/23_containers/unordered_set/insert/hash_policy.cc: Adapt.
    * testsuite/23_containers/unordered_set/max_load_factor/robustness.cc:
    Adapt.
    * testsuite/performance/23_containers/insert/54075.cc: Adapt.
    * testsuite/performance/23_containers/insert_erase/41975.cc: Adapt.
    * testsuite/performance/23_containers/insert_erase/
    unordered_small_size.cc: Adapt.

Tested under Linux x86_64.

François


diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h
index ad07a36eb83..d09c851e8a4 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -69,31 +69,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*  and returns a bool-like value that is true if the two objects
*  are considered equal.
*
-   *  @tparam _H1  The hash function. A unary function object with
+   *  @tparam _Hash  The hash function. A unary function object with
*  argument type _Key and result type size_t. Return values should
*  be distributed over the entire range [0, numeric_limits:::max()].
*
-   *  @tparam _H2  The range-hashing function (in the terminology of
-   *  Tavori and Dreizin).  A binary function object whose argument
-   *  types and result type are all size_t.  Given arguments r and N,
-   *  the return value is in the range [0, N).
-   *
-   *  @tparam _Hash  The ranged hash function (Tavori and Dreizin). A
-   *  binary function whose argument types are _Key and size_t and
-   *  whose result type is size_t.  Given arguments k and N, the
-   *  return value is in the range [0, N).  Default: hash(k, N) =
-   *  h2(h1(k), N).  If _Hash is anything other than the default, _H1
-   *  and _H2 are ignored.
-   *
-   *  @tparam _RehashPolicy  Policy class with three members, all of
-   *  which govern the bucket count. _M_next_bkt(n) returns a bucket
-   *  count no smaller than n.  _M_bkt_for_elements(n) returns a
-   *  bucket count appropriate for an element count of n.
-   *  _M_need_rehash(n_bkt, n_elt, n_ins) determines whether, if the
-   *  current bucket count is n_bkt and the current element count is
-   *  n_elt, we need to increase the bucket count.  If so, returns
-   *  make_pair(true, n), where n is the new bucket count.  If not,
-   *  returns make_pair(false, )
+   *  @tparam _RehashPolicy  Policy class with three members, all of which
+   *  govern the bucket count. _M_next_bkt(n) returns a bucket count no smaller
+   *  than n. _M_bkt_for_elements(n) returns a bucket count appropriate for an
+   *  element count of n. _M_need_rehash(n_bkt, n_elt, n_ins) determines
+   *  whether, if the current bucket count is n_bkt and the current element
+   *  count is n_elt, we need to increase the bucket count for n_ins insertions.
+   *  If so, returns make_pair(true, n), where n is the new bucket count. If
+   *  not, returns make_pair(false, )
*
*  @tparam _Traits  Compile-time class with three boolean
*  std::integral_constant members:  __cache_hash_code, __constant_iterators,
@@ -168,19 +155,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*/
   template
+	   typename _Hash, typename _RehashPolicy, typename _Traits>
 class