DenseMap: Provide a move ctor and move semantics for operator[] and FindAndConstruct.
authorBenjamin Kramer <benny.kra@googlemail.com>
Sun, 27 May 2012 17:38:30 +0000 (17:38 +0000)
committerBenjamin Kramer <benny.kra@googlemail.com>
Sun, 27 May 2012 17:38:30 +0000 (17:38 +0000)
The only missing part is insert(), which uses a pair of parameters and I haven't
figured out how to convert it to rvalue references. It's now possible to use a
DenseMap with std::unique_ptr values :)

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@157539 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/ADT/DenseMap.h

index 4b0df5d371272815a6e6fef47378e73e8a59663c..1fc0eed706ed452962a58fc6d1feefbfcb4f2e13 100644 (file)
@@ -53,6 +53,13 @@ public:
     CopyFrom(other);
   }
 
+#if LLVM_USE_RVALUE_REFERENCES
+  DenseMap(DenseMap &&other) {
+    init(0);
+    swap(other);
+  }
+#endif
+
   explicit DenseMap(unsigned NumInitBuckets = 0) {
     init(NumInitBuckets);
   }
@@ -225,11 +232,33 @@ public:
     return FindAndConstruct(Key).second;
   }
 
+#if LLVM_USE_RVALUE_REFERENCES
+  value_type& FindAndConstruct(KeyT &&Key) {
+    BucketT *TheBucket;
+    if (LookupBucketFor(Key, TheBucket))
+      return *TheBucket;
+
+    return *InsertIntoBucket(Key, ValueT(), TheBucket);
+  }
+
+  ValueT &operator[](KeyT &&Key) {
+    return FindAndConstruct(Key).second;
+  }
+#endif
+
   DenseMap& operator=(const DenseMap& other) {
     CopyFrom(other);
     return *this;
   }
 
+#if LLVM_USE_RVALUE_REFERENCES
+  DenseMap& operator=(DenseMap &&other) {
+    DestroyAll();
+    init(0);
+    swap(other);
+  }
+#endif
+
   /// isPointerIntoBucketsArray - Return true if the specified pointer points
   /// somewhere into the DenseMap's array of buckets (i.e. either to a key or
   /// value in the DenseMap).
@@ -287,6 +316,33 @@ private:
 
   BucketT *InsertIntoBucket(const KeyT &Key, const ValueT &Value,
                             BucketT *TheBucket) {
+    TheBucket = InsertIntoBucketImpl(Key, TheBucket);
+
+    TheBucket->first = Key;
+    new (&TheBucket->second) ValueT(Value);
+    return TheBucket;
+  }
+
+#if LLVM_USE_RVALUE_REFERENCES
+  BucketT *InsertIntoBucket(const KeyT &Key, ValueT &&Value,
+                            BucketT *TheBucket) {
+    TheBucket = InsertIntoBucketImpl(Key, TheBucket);
+
+    TheBucket->first = Key;
+    new (&TheBucket->second) ValueT(std::move(Value));
+    return TheBucket;
+  }
+
+  BucketT *InsertIntoBucket(KeyT &&Key, ValueT &&Value, BucketT *TheBucket) {
+    TheBucket = InsertIntoBucketImpl(Key, TheBucket);
+
+    TheBucket->first = std::move(Key);
+    new (&TheBucket->second) ValueT(std::move(Value));
+    return TheBucket;
+  }
+#endif
+
+  BucketT *InsertIntoBucketImpl(const KeyT &Key, BucketT *TheBucket) {
     // If the load of the hash table is more than 3/4, or if fewer than 1/8 of
     // the buckets are empty (meaning that many are filled with tombstones),
     // grow the table.
@@ -310,8 +366,6 @@ private:
     if (!KeyInfoT::isEqual(TheBucket->first, getEmptyKey()))
       --NumTombstones;
 
-    TheBucket->first = Key;
-    new (&TheBucket->second) ValueT(Value);
     return TheBucket;
   }