diff mbox series

Remove redundant accessors in hash tables

Message ID 20190515153716.GX2599@redhat.com
State New
Headers show
Series Remove redundant accessors in hash tables | expand

Commit Message

Jonathan Wakely May 15, 2019, 3:37 p.m. UTC
François,
I noticed that _Hash_code_base and _Hashtable_base have a number of
member functions which are overloaded for const and non-const:

    const _Equal&
    _M_eq() const { return _EqualEBO::_S_cget(*this); }

    _Equal&
    _M_eq() { return _EqualEBO::_S_get(*this); }

The non-const ones seem to be unnecessary. They're used in the _M_swap
member functions, but all other uses could (and probably should) call
the const overload to get a const reference to the function object.

If we make the _M_swap members use the EBO accessors directly then we
can get rid of the non-const accessors. That makes overload resolution
simpler for the compiler (as there's only one function to choose from)
and should result in slightly smaller code when inlining is not
enabled.

Do you see any problem with this patch?

Comments

François Dumont May 16, 2019, 5:47 a.m. UTC | #1
On 5/15/19 5:37 PM, Jonathan Wakely wrote:
> François,
> I noticed that _Hash_code_base and _Hashtable_base have a number of
> member functions which are overloaded for const and non-const:
>
>    const _Equal&
>    _M_eq() const { return _EqualEBO::_S_cget(*this); }
>
>    _Equal&
>    _M_eq() { return _EqualEBO::_S_get(*this); }
>
> The non-const ones seem to be unnecessary. They're used in the _M_swap
> member functions, but all other uses could (and probably should) call
> the const overload to get a const reference to the function object.
>
> If we make the _M_swap members use the EBO accessors directly then we
> can get rid of the non-const accessors. That makes overload resolution
> simpler for the compiler (as there's only one function to choose from)
> and should result in slightly smaller code when inlining is not
> enabled.
>
> Do you see any problem with this patch?
>
>
I think it is more a Pavlov behavior, always providing const and 
non-const no matter what.

No problem to simplify this.
Jonathan Wakely May 16, 2019, 10:05 a.m. UTC | #2
On 16/05/19 07:47 +0200, François Dumont wrote:
>On 5/15/19 5:37 PM, Jonathan Wakely wrote:
>>François,
>>I noticed that _Hash_code_base and _Hashtable_base have a number of
>>member functions which are overloaded for const and non-const:
>>
>>   const _Equal&
>>   _M_eq() const { return _EqualEBO::_S_cget(*this); }
>>
>>   _Equal&
>>   _M_eq() { return _EqualEBO::_S_get(*this); }
>>
>>The non-const ones seem to be unnecessary. They're used in the _M_swap
>>member functions, but all other uses could (and probably should) call
>>the const overload to get a const reference to the function object.
>>
>>If we make the _M_swap members use the EBO accessors directly then we
>>can get rid of the non-const accessors. That makes overload resolution
>>simpler for the compiler (as there's only one function to choose from)
>>and should result in slightly smaller code when inlining is not
>>enabled.
>>
>>Do you see any problem with this patch?
>>
>>
>I think it is more a Pavlov behavior, always providing const and 
>non-const no matter what.
>
>No problem to simplify this.

OK, tested powerpc64le-linux, committed to trunk.
Jonathan Wakely May 16, 2019, 12:30 p.m. UTC | #3
On 16/05/19 11:05 +0100, Jonathan Wakely wrote:
>On 16/05/19 07:47 +0200, François Dumont wrote:
>>On 5/15/19 5:37 PM, Jonathan Wakely wrote:
>>>François,
>>>I noticed that _Hash_code_base and _Hashtable_base have a number of
>>>member functions which are overloaded for const and non-const:
>>>
>>>   const _Equal&
>>>   _M_eq() const { return _EqualEBO::_S_cget(*this); }
>>>
>>>   _Equal&
>>>   _M_eq() { return _EqualEBO::_S_get(*this); }
>>>
>>>The non-const ones seem to be unnecessary. They're used in the _M_swap
>>>member functions, but all other uses could (and probably should) call
>>>the const overload to get a const reference to the function object.
>>>
>>>If we make the _M_swap members use the EBO accessors directly then we
>>>can get rid of the non-const accessors. That makes overload resolution
>>>simpler for the compiler (as there's only one function to choose from)
>>>and should result in slightly smaller code when inlining is not
>>>enabled.
>>>
>>>Do you see any problem with this patch?
>>>
>>>
>>I think it is more a Pavlov behavior, always providing const and 
>>non-const no matter what.
>>
>>No problem to simplify this.
>
>OK, tested powerpc64le-linux, committed to trunk.

I don't see a need for the _Hashtable_ebo_helper member functions to
be static. They return a member of *this, but are static so *this has
to be passed as a parameter. We could just make them non-static.

It seems to have always been that way since the first version of the
patch that added the helpers:
https://gcc.gnu.org/ml/libstdc++/2011-12/msg00139.html

This patch passes all tests. I plan to commit this to trunk too.
Jonathan Wakely May 16, 2019, 1:24 p.m. UTC | #4
On 16/05/19 13:30 +0100, Jonathan Wakely wrote:
>On 16/05/19 11:05 +0100, Jonathan Wakely wrote:
>>On 16/05/19 07:47 +0200, François Dumont wrote:
>>>On 5/15/19 5:37 PM, Jonathan Wakely wrote:
>>>>François,
>>>>I noticed that _Hash_code_base and _Hashtable_base have a number of
>>>>member functions which are overloaded for const and non-const:
>>>>
>>>>   const _Equal&
>>>>   _M_eq() const { return _EqualEBO::_S_cget(*this); }
>>>>
>>>>   _Equal&
>>>>   _M_eq() { return _EqualEBO::_S_get(*this); }
>>>>
>>>>The non-const ones seem to be unnecessary. They're used in the _M_swap
>>>>member functions, but all other uses could (and probably should) call
>>>>the const overload to get a const reference to the function object.
>>>>
>>>>If we make the _M_swap members use the EBO accessors directly then we
>>>>can get rid of the non-const accessors. That makes overload resolution
>>>>simpler for the compiler (as there's only one function to choose from)
>>>>and should result in slightly smaller code when inlining is not
>>>>enabled.
>>>>
>>>>Do you see any problem with this patch?
>>>>
>>>>
>>>I think it is more a Pavlov behavior, always providing const and 
>>>non-const no matter what.
>>>
>>>No problem to simplify this.
>>
>>OK, tested powerpc64le-linux, committed to trunk.
>
>I don't see a need for the _Hashtable_ebo_helper member functions to
>be static. They return a member of *this, but are static so *this has
>to be passed as a parameter. We could just make them non-static.
>
>It seems to have always been that way since the first version of the
>patch that added the helpers:
>https://gcc.gnu.org/ml/libstdc++/2011-12/msg00139.html
>
>This patch passes all tests. I plan to commit this to trunk too.

And another one (which I've actually had sitting in a local branch for
a few years!)
diff mbox series

Patch

diff --git a/libstdc++-v3/include/bits/hashtable_policy.h b/libstdc++-v3/include/bits/hashtable_policy.h
index 9505fb8d261..5ff90c952ba 100644
--- a/libstdc++-v3/include/bits/hashtable_policy.h
+++ b/libstdc++-v3/include/bits/hashtable_policy.h
@@ -1229,21 +1229,16 @@  namespace __detail
       void
       _M_swap(_Hash_code_base& __x)
       {
-	std::swap(_M_extract(), __x._M_extract());
-	std::swap(_M_ranged_hash(), __x._M_ranged_hash());
+	std::swap(__ebo_extract_key::_S_get(*this),
+		  __ebo_extract_key::_S_get(__x));
+	std::swap(__ebo_hash::_S_get(*this), __ebo_hash::_S_get(__x));
       }
 
       const _ExtractKey&
       _M_extract() const { return __ebo_extract_key::_S_cget(*this); }
 
-      _ExtractKey&
-      _M_extract() { return __ebo_extract_key::_S_get(*this); }
-
       const _Hash&
       _M_ranged_hash() const { return __ebo_hash::_S_cget(*this); }
-
-      _Hash&
-      _M_ranged_hash() { return __ebo_hash::_S_get(*this); }
     };
 
   // No specialization for ranged hash function while caching hash codes.
@@ -1326,28 +1321,20 @@  namespace __detail
       void
       _M_swap(_Hash_code_base& __x)
       {
-	std::swap(_M_extract(), __x._M_extract());
-	std::swap(_M_h1(), __x._M_h1());
-	std::swap(_M_h2(), __x._M_h2());
+	std::swap(__ebo_extract_key::_S_get(*this),
+		  __ebo_extract_key::_S_get(__x));
+	std::swap(__ebo_h1::_S_get(*this), __ebo_h1::_S_get(__x));
+	std::swap(__ebo_h2::_S_get(*this), __ebo_h2::_S_get(__x));
       }
 
       const _ExtractKey&
       _M_extract() const { return __ebo_extract_key::_S_cget(*this); }
 
-      _ExtractKey&
-      _M_extract() { return __ebo_extract_key::_S_get(*this); }
-
       const _H1&
       _M_h1() const { return __ebo_h1::_S_cget(*this); }
 
-      _H1&
-      _M_h1() { return __ebo_h1::_S_get(*this); }
-
       const _H2&
       _M_h2() const { return __ebo_h2::_S_cget(*this); }
-
-      _H2&
-      _M_h2() { return __ebo_h2::_S_get(*this); }
     };
 
   /// Specialization: hash function and range-hashing function,
@@ -1418,28 +1405,20 @@  namespace __detail
       void
       _M_swap(_Hash_code_base& __x)
       {
-	std::swap(_M_extract(), __x._M_extract());
-	std::swap(_M_h1(), __x._M_h1());
-	std::swap(_M_h2(), __x._M_h2());
+	std::swap(__ebo_extract_key::_S_get(*this),
+		  __ebo_extract_key::_S_get(__x));
+	std::swap(__ebo_h1::_S_get(*this), __ebo_h1::_S_get(__x));
+	std::swap(__ebo_h2::_S_get(*this), __ebo_h2::_S_get(__x));
       }
 
       const _ExtractKey&
       _M_extract() const { return __ebo_extract_key::_S_cget(*this); }
 
-      _ExtractKey&
-      _M_extract() { return __ebo_extract_key::_S_get(*this); }
-
       const _H1&
       _M_h1() const { return __ebo_h1::_S_cget(*this); }
 
-      _H1&
-      _M_h1() { return __ebo_h1::_S_get(*this); }
-
       const _H2&
       _M_h2() const { return __ebo_h2::_S_cget(*this); }
-
-      _H2&
-      _M_h2() { return __ebo_h2::_S_get(*this); }
     };
 
   /**
@@ -1851,14 +1830,11 @@  namespace __detail
     _M_swap(_Hashtable_base& __x)
     {
       __hash_code_base::_M_swap(__x);
-      std::swap(_M_eq(), __x._M_eq());
+      std::swap(_EqualEBO::_S_get(*this), _EqualEBO::_S_get(__x));
     }
 
     const _Equal&
     _M_eq() const { return _EqualEBO::_S_cget(*this); }
-
-    _Equal&
-    _M_eq() { return _EqualEBO::_S_get(*this); }
   };
 
   /**