77
88module containers.hashmap ;
99
10+ private import core.lifetime : move;
1011private import containers.internal.hash;
1112private import containers.internal.node : shouldAddGCRange;
1213private import std.experimental.allocator.mallocator : Mallocator;
@@ -181,7 +182,7 @@ struct HashMap(K, V, Allocator = Mallocator, alias hashFunction = generateHash!K
181182 */
182183 void opIndexAssign (V value, const K key)
183184 {
184- insert(key, value);
185+ insert(key, move (mutable( value)) );
185186 }
186187
187188 /**
@@ -257,7 +258,7 @@ struct HashMap(K, V, Allocator = Mallocator, alias hashFunction = generateHash!K
257258 auto app = appender! (K[])();
258259 foreach (ref const bucket; buckets)
259260 {
260- foreach (item; bucket)
261+ foreach (ref item; bucket)
261262 app.put(cast (K) item.key);
262263 }
263264 return app.data;
@@ -364,6 +365,8 @@ private:
364365 enum bool useGC = supportGC && (shouldAddGCRange! K || shouldAddGCRange! V);
365366 alias Hash = typeof ({ K k = void ; return hashFunction (k); }());
366367
368+ static ref ContainerStorageType! T mutable (T)(ref T value) { return * cast (ContainerStorageType! T* )&value; }
369+
367370 enum IterType: ubyte
368371 {
369372 key, value, both
@@ -472,7 +475,7 @@ private:
472475
473476 Node* insert (const K key, V value)
474477 {
475- return insert (key, value, hashFunction(key));
478+ return insert (key, move(mutable( value)) , hashFunction(key));
476479 }
477480
478481 Node* insert (const K key, V value, const Hash hash, const bool modifyLength = true )
@@ -484,15 +487,15 @@ private:
484487 {
485488 if (item.hash == hash && item.key == key)
486489 {
487- item.value = value;
490+ item.value = move(mutable( value)) ;
488491 return &item;
489492 }
490493 }
491494 static if (storeHash)
492- Node node = Node(hash, cast (ContainerStorageType! K) key, value);
495+ Node node = Node(hash, cast (ContainerStorageType! K) key, move(mutable( value)) );
493496 else
494- Node node = Node(cast (ContainerStorageType! K) key, value);
495- Node* n = buckets[index].insertAnywhere(node);
497+ Node node = Node(cast (ContainerStorageType! K) key, move(mutable( value)) );
498+ Node* n = buckets[index].insertAnywhere(move( node) );
496499 if (modifyLength)
497500 _length++ ;
498501 if (shouldRehash())
@@ -533,7 +536,8 @@ private:
533536 buckets = cast (Bucket[]) allocator.allocate(newSize);
534537 static if (useGC)
535538 GC .addRange(buckets.ptr, buckets.length * Bucket.sizeof);
536- assert (buckets);
539+ if (newLength)
540+ assert (buckets);
537541 assert (buckets.length == newLength);
538542 foreach (ref bucket; buckets)
539543 {
@@ -545,8 +549,8 @@ private:
545549
546550 foreach (ref bucket; oldBuckets)
547551 {
548- foreach (node; bucket)
549- insert(cast (K) node.key, node.value, node.hash, false );
552+ foreach (ref node; bucket)
553+ insert(cast (K) node.key, move( node.value) , node.hash, false );
550554 typeid (typeof (bucket)).destroy (&bucket);
551555 }
552556 static if (useGC)
@@ -780,3 +784,9 @@ version(emsi_containers_unittest) unittest
780784 foreach (k, ref v; hm) { v++ ; }
781785 assert (hm[" a" ] == 2 );
782786}
787+
788+ version (emsi_containers_unittest) unittest
789+ {
790+ static struct S { @disable this (this ); }
791+ alias HM = HashMap! (int , S);
792+ }
0 commit comments