[Bf-blender-cvs] [9f83ef2149e] master: BLI: make different pointer types compatible in hash tables

Jacques Lucke noreply at git.blender.org
Mon Nov 21 12:03:37 CET 2022


Commit: 9f83ef2149e085f847ac5bde353ba9682036cede
Author: Jacques Lucke
Date:   Mon Nov 21 12:02:10 2022 +0100
Branches: master
https://developer.blender.org/rB9f83ef2149e085f847ac5bde353ba9682036cede

BLI: make different pointer types compatible in hash tables

For example, this allows doing a lookup using a raw pointer in a
hash table that uses `std::unique_ptr` as key.

===================================================================

M	source/blender/blenlib/BLI_hash.hh
M	source/blender/blenlib/BLI_hash_tables.hh
M	source/blender/blenlib/BLI_map.hh
M	source/blender/blenlib/BLI_set.hh
M	source/blender/blenlib/BLI_vector_set.hh
M	source/blender/blenlib/tests/BLI_set_test.cc

===================================================================

diff --git a/source/blender/blenlib/BLI_hash.hh b/source/blender/blenlib/BLI_hash.hh
index 693d4a8a71c..c29dc74599a 100644
--- a/source/blender/blenlib/BLI_hash.hh
+++ b/source/blender/blenlib/BLI_hash.hh
@@ -246,18 +246,17 @@ uint64_t get_default_hash_4(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &
   return h1 ^ (h2 * 19349669) ^ (h3 * 83492791) ^ (h4 * 3632623);
 }
 
-template<typename T> struct DefaultHash<std::unique_ptr<T>> {
-  uint64_t operator()(const std::unique_ptr<T> &value) const
+/** Support hashing different kinds of pointer types. */
+template<typename T> struct PointerHashes {
+  template<typename U> uint64_t operator()(const U &value) const
   {
-    return get_default_hash(value.get());
+    return get_default_hash(&*value);
   }
 };
 
-template<typename T> struct DefaultHash<std::shared_ptr<T>> {
-  uint64_t operator()(const std::shared_ptr<T> &value) const
-  {
-    return get_default_hash(value.get());
-  }
+template<typename T> struct DefaultHash<std::unique_ptr<T>> : public PointerHashes<T> {
+};
+template<typename T> struct DefaultHash<std::shared_ptr<T>> : public PointerHashes<T> {
 };
 
 template<typename T> struct DefaultHash<std::reference_wrapper<T>> {
diff --git a/source/blender/blenlib/BLI_hash_tables.hh b/source/blender/blenlib/BLI_hash_tables.hh
index de65c58d4db..fff2411f94c 100644
--- a/source/blender/blenlib/BLI_hash_tables.hh
+++ b/source/blender/blenlib/BLI_hash_tables.hh
@@ -331,11 +331,26 @@ class HashTableStats {
  * requires the parameters to be of type T. Our hash tables support lookups using other types
  * without conversion, therefore DefaultEquality needs to be more generic.
  */
-struct DefaultEquality {
+template<typename T> struct DefaultEquality {
   template<typename T1, typename T2> bool operator()(const T1 &a, const T2 &b) const
   {
     return a == b;
   }
 };
 
+/**
+ * Support comparing different kinds of raw and smart pointers.
+ */
+struct PointerComparison {
+  template<typename T1, typename T2> bool operator()(const T1 &a, const T2 &b) const
+  {
+    return &*a == &*b;
+  }
+};
+
+template<typename T> struct DefaultEquality<std::unique_ptr<T>> : public PointerComparison {
+};
+template<typename T> struct DefaultEquality<std::shared_ptr<T>> : public PointerComparison {
+};
+
 }  // namespace blender
diff --git a/source/blender/blenlib/BLI_map.hh b/source/blender/blenlib/BLI_map.hh
index 6d281420c47..fb048102153 100644
--- a/source/blender/blenlib/BLI_map.hh
+++ b/source/blender/blenlib/BLI_map.hh
@@ -92,7 +92,7 @@ template<
      * The equality operator used to compare keys. By default it will simply compare keys using the
      * `==` operator.
      */
-    typename IsEqual = DefaultEquality,
+    typename IsEqual = DefaultEquality<Key>,
     /**
      * This is what will actually be stored in the hash table array. At a minimum a slot has to be
      * able to hold a key, a value and information about whether the slot is empty, occupied or
@@ -1263,7 +1263,7 @@ template<typename Key,
                                                                        sizeof(Value)),
          typename ProbingStrategy = DefaultProbingStrategy,
          typename Hash = DefaultHash<Key>,
-         typename IsEqual = DefaultEquality,
+         typename IsEqual = DefaultEquality<Key>,
          typename Slot = typename DefaultMapSlot<Key, Value>::type>
 using RawMap =
     Map<Key, Value, InlineBufferCapacity, ProbingStrategy, Hash, IsEqual, Slot, RawAllocator>;
diff --git a/source/blender/blenlib/BLI_set.hh b/source/blender/blenlib/BLI_set.hh
index 8fb618edeb6..548195e48f7 100644
--- a/source/blender/blenlib/BLI_set.hh
+++ b/source/blender/blenlib/BLI_set.hh
@@ -89,7 +89,7 @@ template<
      * The equality operator used to compare keys. By default it will simply compare keys using the
      * `==` operator.
      */
-    typename IsEqual = DefaultEquality,
+    typename IsEqual = DefaultEquality<Key>,
     /**
      * This is what will actually be stored in the hash table array. At a minimum a slot has to
      * be able to hold a key and information about whether the slot is empty, occupied or removed.
@@ -949,7 +949,7 @@ template<typename Key,
          int64_t InlineBufferCapacity = default_inline_buffer_capacity(sizeof(Key)),
          typename ProbingStrategy = DefaultProbingStrategy,
          typename Hash = DefaultHash<Key>,
-         typename IsEqual = DefaultEquality,
+         typename IsEqual = DefaultEquality<Key>,
          typename Slot = typename DefaultSetSlot<Key>::type>
 using RawSet = Set<Key, InlineBufferCapacity, ProbingStrategy, Hash, IsEqual, Slot, RawAllocator>;
 
diff --git a/source/blender/blenlib/BLI_vector_set.hh b/source/blender/blenlib/BLI_vector_set.hh
index d182e1f1678..9805e8a7d59 100644
--- a/source/blender/blenlib/BLI_vector_set.hh
+++ b/source/blender/blenlib/BLI_vector_set.hh
@@ -72,7 +72,7 @@ template<
      * The equality operator used to compare keys. By default it will simply compare keys using the
      * `==` operator.
      */
-    typename IsEqual = DefaultEquality,
+    typename IsEqual = DefaultEquality<Key>,
     /**
      * This is what will actually be stored in the hash table array. At a minimum a slot has to be
      * able to hold an array index and information about whether the slot is empty, occupied or
@@ -874,7 +874,7 @@ class VectorSet {
 template<typename Key,
          typename ProbingStrategy = DefaultProbingStrategy,
          typename Hash = DefaultHash<Key>,
-         typename IsEqual = DefaultEquality,
+         typename IsEqual = DefaultEquality<Key>,
          typename Slot = typename DefaultVectorSetSlot<Key>::type>
 using RawVectorSet = VectorSet<Key, ProbingStrategy, Hash, IsEqual, Slot, RawAllocator>;
 
diff --git a/source/blender/blenlib/tests/BLI_set_test.cc b/source/blender/blenlib/tests/BLI_set_test.cc
index 79439eb9079..8e311eaf2e4 100644
--- a/source/blender/blenlib/tests/BLI_set_test.cc
+++ b/source/blender/blenlib/tests/BLI_set_test.cc
@@ -393,7 +393,7 @@ TEST(set, IntrusiveIntKey)
       2,
       DefaultProbingStrategy,
       DefaultHash<int>,
-      DefaultEquality,
+      DefaultEquality<int>,
       IntegerSetSlot<int, 100, 200>>
       set;
   EXPECT_TRUE(set.add(4));
@@ -589,6 +589,17 @@ TEST(set, RemoveIf)
   }
 }
 
+TEST(set, RemoveUniquePtrWithRaw)
+{
+  Set<std::unique_ptr<int>> set;
+  std::unique_ptr<int> a = std::make_unique<int>(5);
+  int *a_ptr = a.get();
+  set.add(std::move(a));
+  EXPECT_EQ(set.size(), 1);
+  set.remove_as(a_ptr);
+  EXPECT_TRUE(set.is_empty());
+}
+
 /**
  * Set this to 1 to activate the benchmark. It is disabled by default, because it prints a lot.
  */



More information about the Bf-blender-cvs mailing list