byKeyValue

@safe @trusted
byKeyValue
(
SomeMap
)
(
auto ref return SomeMap c
)
if (
isInstanceOf!(OpenHashMap, SomeMap) &&
SomeMap.hasValue
)

Return Value

Type: auto

range that iterates through the key-value-pairs of c in undefined order.

Examples

make range from l-value and r-value. element access is always const

1 version(showEntries) dbg();
2 
3 import core.exception : RangeError, AssertError;
4 import std.typecons : Nullable;
5 import nxt.digestx.fnv : FNV;
6 import nxt.array_help : s;
7 debug import std.exception : assertThrown, assertNotThrown;
8 
9 import std.algorithm.searching : count;
10 alias K = Nullable!(uint, uint.max);
11 alias X = OpenHashSet!(K,
12                        FNV!(64, true),
13                        defaultKeyEqualPredOf!K,
14                        Mallocator.instance,
15                        true);
16 
17 auto k11 = K(11);
18 auto k22 = K(22);
19 auto k33 = K(33);
20 auto ks = [k11, k22, k33].s;
21 auto k44 = K(44);
22 
23 // mutable
24 auto x = X.withElements(ks);
25 assert(!x.contains(k44));
26 assert(!x.containsUsingLinearSearch(k44));
27 assert(x.length == 3);
28 
29 assert(x.byElement.count == x.length);
30 foreach (e; x.byElement)    // from l-value
31 {
32     debug static assert(is(typeof(e) == const(K))); // always const access
33 
34     // range invalidation forbidden:
35     debug
36     {
37         assertThrown!AssertError(x.reserveExtra(1));  // range invalidation
38         assertThrown!AssertError(x.clear());          // range invalidation
39         assertThrown!AssertError(x.insert(k11));      // range invalidation
40         assertThrown!AssertError(x.insertN([k11].s)); // range invalidation
41         assertThrown!AssertError(x.remove(k11));      // range invalidation
42     }
43 
44     // allowed
45     assert(x.contains(e));
46     assert(x.containsUsingLinearSearch(e));
47 
48     const eHit = e in x;
49     assert(eHit);           // found
50     assert(*eHit is e);     // and the value equals what we searched for
51 
52     const eDup = x.dup;     // duplication is `const` and allowed
53 }
54 
55 // const
56 const y = X.withElements(ks);
57 assert(!x.contains(k44));
58 assert(!x.containsUsingLinearSearch(k44));
59 foreach (e; y.byElement)    // from l-value
60 {
61     auto z = y.byElement;   // ok to read-borrow again
62     assert(y.contains(e));
63     assert(y.containsUsingLinearSearch(e));
64     debug static assert(is(typeof(e) == const(K)));
65 }
66 
67 foreach (e; X.withElements([K(11)].s).byElement) // from r-value
68 {
69     assert(e == K(11));
70     debug static assert(is(typeof(e) == const(K))); // always const access
71 }

range checking

1 version(showEntries) dbg();
2 import core.exception : RangeError, AssertError;
3 import std.typecons : Nullable;
4 import nxt.digestx.fnv : FNV;
5 debug import std.exception : assertThrown, assertNotThrown;
6 immutable n = 11;
7 
8 alias K = Nullable!(uint, uint.max);
9 alias V = uint;
10 
11 alias X = OpenHashMap!(K, V, FNV!(64, true));
12 
13 auto s = X.withCapacity(n);
14 
15 void dummy(ref V value) {}
16 
17 debug assertThrown!RangeError(dummy(s[K(0)]));
18 
19 foreach (immutable i; 0 .. n)
20 {
21     const k = K(i);
22     s[k] = V(i);
23     debug assertNotThrown!RangeError(dummy(s[k]));
24 }
25 
26 foreach (immutable i; 0 .. n)
27 {
28     const k = K(i);
29     assert(s.remove(k));
30     debug assertThrown!RangeError(dummy(s[k]));
31 }
32 
33 s[K(0)] = V.init;
34 auto vp = K(0) in s;
35 debug static assert(is(typeof(vp) == V*));
36 assert((*vp) == V.init);
37 
38 assert(s.remove(K(0)));
39 assert(K(0) !in s);
40 
41 X t;
42 t.reserveExtra(4096);
43 
44 t.clear();

class as value

1 version(showEntries) dbg();
2 import core.exception : RangeError, AssertError;
3 import std.typecons : Nullable;
4 debug import std.exception : assertThrown, assertNotThrown;
5 import nxt.digestx.fnv : FNV;
6 
7 immutable n = 11;
8 
9 alias K = Nullable!(uint, uint.max);
10 class V
11 {
12     this(uint data) { this.data = data; }
13     uint data;
14 }
15 
16 alias X = OpenHashMap!(K, V, FNV!(64, true));
17 
18 auto s = X.withCapacity(n);
19 
20 void dummy(ref V value) {}
21 
22 debug assertThrown!RangeError(dummy(s[K(0)]));
23 
24 foreach (immutable i; 0 .. n)
25 {
26     const k = K(i);
27     s[k] = new V(i);
28     debug assertNotThrown!RangeError(dummy(s[k]));
29 }
30 
31 // test range
32 {
33     auto sr = s.byKeyValue; // scoped range
34     assert(sr.length == n);
35     foreach (immutable i; 0 .. n)
36     {
37         sr.popFront();
38         assert(sr.length == n - i - 1);
39     }
40 }
41 
42 foreach (immutable i; 0 .. n)
43 {
44     const k = K(i);
45     assert(s.remove(k));
46     debug assertThrown!RangeError(dummy(s[k]));
47 }
48 
49 s[K(0)] = V.init;
50 auto vp = K(0) in s;
51 debug static assert(is(typeof(vp) == V*));
52 
53 assert(s.remove(K(0)));
54 assert(K(0) !in s);
55 
56 X t;
57 t.reserveExtra(4096);

constness inference of ranges

1 version(showEntries) dbg();
2 import std.typecons : Nullable;
3 import nxt.digestx.fnv : FNV;
4 
5 alias K = Nullable!(uint, uint.max);
6 class V
7 {
8     this(uint data) { this.data = data; }
9     uint data;
10 }
11 
12 alias X = OpenHashMap!(K, V, FNV!(64, true));
13 const x = X();
14 
15 foreach (ref e; x.byKey)
16 {
17     debug static assert(is(typeof(e) == const(X.KeyType)));
18 }
19 
20 foreach (ref e; x.byValue)
21 {
22     debug static assert(is(typeof(e) == const(X.ValueType)));
23 }
24 
25 foreach (e; x.byKeyValue)
26 {
27     debug static assert(is(typeof(e.key) == const(X.KeyType)));
28     debug static assert(is(typeof(e.value) == const(X.ValueType)));
29     debug static assert(is(typeof(e) == const(X.ElementType)));
30 }

range key constness and value mutability with class value

1 version(showEntries) dbg();
2 import std.typecons : Nullable;
3 import nxt.digestx.fnv : FNV;
4 
5 struct S
6 {
7     uint value;
8 }
9 alias K = Nullable!(S, S(uint.min)); // use uint.min to trigger use of faster `Allocator.allocateZeroed`
10 
11 class V
12 {
13     this(uint data) { this.data = data; }
14     uint data;
15 }
16 
17 alias X = OpenHashMap!(K, V, FNV!(64, true));
18 auto x = X();
19 
20 x[K(S(42))] = new V(43);
21 
22 assert(x.length == 1);
23 
24 foreach (e; x.byValue)      // `e` is auto ref
25 {
26     debug static assert(is(typeof(e) == X.ValueType)); // mutable access to value
27     assert(e.data == 43);
28 
29     // value mutation side effects
30     e.data += 1;
31     assert(e.data == 44);
32     e.data -= 1;
33     assert(e.data == 43);
34 }
35 
36 foreach (ref e; x.byKeyValue)   // `e` is auto ref
37 {
38     debug static assert(is(typeof(e.key) == const(X.KeyType))); // const access to key
39     debug static assert(is(typeof(e.value) == X.ValueType)); // mutable access to value
40 
41     assert(e.key.value == 42);
42     assert(e.value.data == 43);
43 
44     // key cannot be mutated
45     debug static assert(!__traits(compiles, { e.key.value += 1; }));
46 
47     // value mutation side effects
48     e.value.data += 1;
49     assert(e.value.data == 44);
50     e.value.data -= 1;
51     assert(e.value.data == 43);
52 }

range key constness and value mutability with class key and class value

1 import nxt.digestx.fnv : FNV;
2 
3 version(showEntries) dbg();
4 class K
5 {
6     this(uint value)
7     {
8         this.value = value;
9     }
10 
11     @property bool opEquals(const scope typeof(this) rhs) const
12     {
13         return value == rhs.value;
14     }
15 
16     uint value;
17 }
18 
19 class V
20 {
21     this(uint data) { this.data = data; }
22     uint data;
23 }
24 
25 alias X = OpenHashMap!(K, V, FNV!(64, true));
26 auto x = X();
27 
28 x[new K(42)] = new V(43);
29 
30 assert(x.length == 1);
31 
32 foreach (e; x.byValue)      // `e` is auto ref
33 {
34     debug static assert(is(typeof(e) == X.ValueType)); // mutable access to value
35     assert(e.data == 43);
36 
37     // value mutation side effects
38     e.data += 1;
39     assert(e.data == 44);
40     e.data -= 1;
41     assert(e.data == 43);
42 }
43 
44 foreach (ref e; x.byKeyValue)   // `e` is auto ref
45 {
46     debug static assert(is(typeof(e.key) == X.KeyType)); // mutable access to class key
47     debug static assert(is(typeof(e.value) == X.ValueType)); // mutable access to value
48 
49     assert(e.key.value == 42);
50     assert(e.value.data == 43);
51 
52     // class key itself should not be mutable
53     debug static assert(!__traits(compiles, { e.key = null; }));
54 
55     // members of key can be mutated
56     debug static assert(__traits(compiles, { e.key.value += 1; }));
57 
58     // value mutation side effects
59     e.value.data += 1;
60     assert(e.value.data == 44);
61     e.value.data -= 1;
62     assert(e.value.data == 43);
63 }

range key constness and value mutability with class key and class value

1 import nxt.digestx.fnv : FNV;
2 version(showEntries) dbg();
3 class K
4 {
5     this(uint value)
6     {
7         this.value = value;
8     }
9     uint value;
10 }
11 
12 struct V
13 {
14     this(uint data) { this.data = data; }
15     @disable this(this);
16     uint data;
17 }
18 
19 alias X = OpenHashMap!(K, V, FNV!(64, true));
20 auto x = X();
21 
22 scope key42 = new K(42);
23 x[key42] = V(43);
24 
25 assert(x.length == 1);
26 
27 foreach (ref e; x.byValue)  // `e` is auto ref
28 {
29     debug static assert(is(typeof(e) == X.ValueType)); // mutable access to value
30     assert(e.data == 43);
31 
32     // value mutation side effects
33     e.data += 1;
34     assert(e.data == 44);
35     e.data -= 1;
36     assert(e.data == 43);
37 }
38 
39 foreach (ref e; x.byKeyValue) // `e` is auto ref
40 {
41     debug static assert(is(typeof(e.key) == X.KeyType)); // mutable access to class key
42     debug static assert(is(typeof(e.value) == X.ValueType)); // mutable access to value
43 
44     assert(e.key.value == 42);
45     assert(e.value.data == 43);
46 
47     // value mutation side effects
48     e.value.data += 1;
49     assert(e.value.data == 44);
50     e.value.data -= 1;
51     assert(e.value.data == 43);
52 }
53 
54 assert(x.length == 1);
55 
56 assert(x.remove(key42));
57 assert(x.length == 0);
58 
59 x[key42] = V(43);
60 assert(x.length == 1);

Meta