DenseMap: Provide a move ctor and move semantics for operator[] and FindAndConstruct.

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 :)

llvm-svn: 157539
This commit is contained in:
Benjamin Kramer 2012-05-27 17:38:30 +00:00
parent fd91e72ee2
commit 1e165f0343
1 changed files with 56 additions and 2 deletions

View 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;
}