Patchwork [v3] Add hash<shared_ptr> and hash<unique_ptr>

login
register
mail settings
Submitter Paolo Carlini
Date June 11, 2010, 4 p.m.
Message ID <4C125D99.4090109@oracle.com>
Download mbox | patch
Permalink /patch/55341/
State New
Headers show

Comments

Paolo Carlini - June 11, 2010, 4 p.m.
Hi all, hi Jon,

I'm about to commit this patch adding two missing std::hash
specializations...

Jon, skimming through unique_ptr.h I don't really understand why we are
using std::tuple instead of the *much* simpler std::pair. Can you? I
think that otherwise we should consider changing that, even if that
means breaking the "ABI" for people already experimenting with the C++0x
unique_ptr, because in the future it will be more and more difficult...
If we can avoid using tuple in unique_ptr, I think <memory> can be made
*much* smaller (it used to be very small), because I'm pretty sure we
don't need the entire <functional>, only some bits, like
functional_hash, and very little else.

Tested x86_64-linux.

Paolo.

/////////////////////
2010-06-11  Paolo Carlini  <paolo.carlini@oracle.com>

	* include/bits/shared_ptr.h (hash<shared_ptr>): Add.
	* include/bits/shared_ptr_base.h (hash<__shared_ptr>): Likewise.
	* include/bits/unique_ptr.h (hash<unique_ptr>): Likewise.
	* testsuite/20_util/shared_ptr/hash/1.cc: New.
	* testsuite/20_util/unique_ptr/hash/1.cc: Likewise.
Jonathan Wakely - June 11, 2010, 4:06 p.m.
On 11 June 2010 17:00, Paolo Carlini wrote:
> Hi all, hi Jon,
>
> I'm about to commit this patch adding two missing std::hash
> specializations...
>
> Jon, skimming through unique_ptr.h I don't really understand why we are
> using std::tuple instead of the *much* simpler std::pair. Can you? I
> think that otherwise we should consider changing that, even if that
> means breaking the "ABI" for people already experimenting with the C++0x
> unique_ptr, because in the future it will be more and more difficult...
> If we can avoid using tuple in unique_ptr, I think <memory> can be made
> *much* smaller (it used to be very small), because I'm pretty sure we
> don't need the entire <functional>, only some bits, like
> functional_hash, and very little else.

Does our tuple benefit from the EBO if the deleter is empty?
Paolo Carlini - June 11, 2010, 4:16 p.m.
On 06/11/2010 06:06 PM, Jonathan Wakely wrote:
> Does our tuple benefit from the EBO if the deleter is empty?
>   
You are right, I think it does now (it didn't at first) and that's a big
advantage of tuple over pair. We should use a compressed_pair, really...
We even had it contributed, at some point, quite similar to the boost
version, I think. Would it be *much* simpler than <tuple>? Probably not
worth the trouble and breaking the "experimental ABI"...

Anyway, I can work immediately on changing <memory> to not include the
whole <functional>, even if <tuple> remains.

Paolo.
Jonathan Wakely - June 12, 2010, 12:58 a.m.
On 11 June 2010 17:16, Paolo Carlini wrote:
> On 06/11/2010 06:06 PM, Jonathan Wakely wrote:
>> Does our tuple benefit from the EBO if the deleter is empty?
>>
> You are right, I think it does now (it didn't at first) and that's a big
> advantage of tuple over pair. We should use a compressed_pair, really...
> We even had it contributed, at some point, quite similar to the boost
> version, I think. Would it be *much* simpler than <tuple>? Probably not
> worth the trouble and breaking the "experimental ABI"...

Hmm, I don't like that the 0x ABI is semi-frozen, so maybe I'm not the
right person to ask, because I say break it early and often while it's
experimental.

> Anyway, I can work immediately on changing <memory> to not include the
> whole <functional>, even if <tuple> remains.

I think that would be a nice improvement.

Patch

Index: include/bits/shared_ptr.h
===================================================================
--- include/bits/shared_ptr.h	(revision 160601)
+++ include/bits/shared_ptr.h	(working copy)
@@ -514,6 +514,16 @@ 
 				  std::forward<_Args>(__args)...);
     }
 
+  /// std::hash specialization for shared_ptr.
+  template<typename _Tp>
+    struct hash<shared_ptr<_Tp>>
+    : public std::unary_function<shared_ptr<_Tp>, size_t>
+    {
+      size_t
+      operator()(const shared_ptr<_Tp>& __s) const
+      { return std::hash<_Tp*>()(__s.get()); }
+    };
+
   // @} group pointer_abstractions
 
 _GLIBCXX_END_NAMESPACE
Index: include/bits/unique_ptr.h
===================================================================
--- include/bits/unique_ptr.h	(revision 160601)
+++ include/bits/unique_ptr.h	(working copy)
@@ -233,7 +233,7 @@ 
   // [unique.ptr.runtime]
   // _GLIBCXX_RESOLVE_LIB_DEFECTS
   // DR 740 - omit specialization for array objects with a compile time length
-  template<typename _Tp, typename _Tp_Deleter> 
+  template<typename _Tp, typename _Tp_Deleter>
     class unique_ptr<_Tp[], _Tp_Deleter>
     {
       typedef std::tuple<_Tp*, _Tp_Deleter>  __tuple_type;
@@ -444,6 +444,19 @@ 
 	       const unique_ptr<_Up, _Up_Deleter>& __y)
     { return !(__x.get() < __y.get()); }
 
+  /// std::hash specialization for unique_ptr.
+  template<typename _Tp, typename _Tp_Deleter>
+    struct hash<unique_ptr<_Tp, _Tp_Deleter>>
+    : public std::unary_function<unique_ptr<_Tp, _Tp_Deleter>, size_t>
+    {
+      size_t
+      operator()(const unique_ptr<_Tp, _Tp_Deleter>& __u) const
+      {
+	typedef unique_ptr<_Tp, _Tp_Deleter> _UP;
+	return std::hash<typename _UP::pointer>()(__u.get());
+      }
+    };
+
   // @} group pointer_abstractions
 
 _GLIBCXX_END_NAMESPACE
Index: include/bits/shared_ptr_base.h
===================================================================
--- include/bits/shared_ptr_base.h	(revision 160601)
+++ include/bits/shared_ptr_base.h	(working copy)
@@ -1164,6 +1164,16 @@ 
 					 std::forward<_Args>(__args)...);
     }
 
+  /// std::hash specialization for __shared_ptr.
+  template<typename _Tp, _Lock_policy _Lp>
+    struct hash<__shared_ptr<_Tp, _Lp>>
+    : public std::unary_function<__shared_ptr<_Tp, _Lp>, size_t>
+    {
+      size_t
+      operator()(const __shared_ptr<_Tp, _Lp>& __s) const
+      { return std::hash<_Tp*>()(__s.get()); }
+    };
+
 _GLIBCXX_END_NAMESPACE
 
 #endif // _SHARED_PTR_BASE_H
Index: testsuite/20_util/unique_ptr/hash/1.cc
===================================================================
--- testsuite/20_util/unique_ptr/hash/1.cc	(revision 0)
+++ testsuite/20_util/unique_ptr/hash/1.cc	(revision 0)
@@ -0,0 +1,48 @@ 
+// { dg-options "-std=gnu++0x" }
+
+// 2010-06-11  Paolo Carlini  <paolo.carlini@oracle.com>
+
+// Copyright (C) 2010 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.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <memory>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+
+  struct T { };
+
+  std::unique_ptr<T>                                 u0(new T);
+  std::hash<std::unique_ptr<T>>                      hu0;
+  std::hash<typename std::unique_ptr<T>::pointer>    hp0;
+
+  VERIFY( hu0(u0) == hp0(u0.get()) );
+
+  std::unique_ptr<T[]>                               u1(new T[10]);
+  std::hash<std::unique_ptr<T[]>>                    hu1;
+  std::hash<typename std::unique_ptr<T[]>::pointer>  hp1;
+
+  VERIFY( hu1(u1) == hp1(u1.get()) );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
Index: testsuite/20_util/shared_ptr/hash/1.cc
===================================================================
--- testsuite/20_util/shared_ptr/hash/1.cc	(revision 0)
+++ testsuite/20_util/shared_ptr/hash/1.cc	(revision 0)
@@ -0,0 +1,48 @@ 
+// { dg-options "-std=gnu++0x" }
+
+// 2010-06-11  Paolo Carlini  <paolo.carlini@oracle.com>
+
+// Copyright (C) 2010 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.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <memory>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+
+  struct T { };
+
+  std::shared_ptr<T>                s0(new T);
+  std::hash<std::shared_ptr<T>>     hs0;
+  std::hash<T*>                     hp0;
+
+  VERIFY( hs0(s0) == hp0(s0.get()) );
+
+  std::__shared_ptr<T>              s1(new T);
+  std::hash<std::__shared_ptr<T>>   hs1;
+  std::hash<T*>                     hp1;
+
+  VERIFY( hs1(s1) == hp1(s1.get()) );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}