make

Undocumented in source. Be warned that the author may not have intended to support it.
version(unittest)
@safe
T
make
(
T
)
(
ulong value
)

Examples

test various things

1 import std.meta : AliasSeq;
2 import std.typecons : Nullable;
3 import std.algorithm.comparison : equal;
4 import nxt.container_traits : mustAddGCRange;
5 import nxt.digestx.fnv : FNV;
6 import nxt.array_help : s;
7 
8 version(showEntries) dbg();
9 const n = 100;
10 
11 void testEmptyAll(K, V, X)(ref X x, size_t n,
12                            scope K[] keys)
13 {
14     assert(x.length == n);
15     foreach (key; keys)
16     {
17         static if (X.hasValue)
18         {
19             const element = X.ElementType(key, V.init);
20         }
21         else
22         {
23             alias element = key;
24         }
25 
26         assert(x.length == n - key.get);
27 
28         const hitPtr = key in x;
29         static if (X.hasValue)
30         {
31             assert(hitPtr && *hitPtr is element.value);
32         }
33         else
34         {
35             assert(hitPtr && *hitPtr is element);
36         }
37 
38         assert(x.remove(key));
39         assert(x.length == n - key.get - 1);
40 
41         static if (!X.hasValue)
42         {
43             assert(!x.contains(key));
44             assert(!x.containsUsingLinearSearch(key));
45         }
46         assert(key !in x);
47         assert(!x.remove(key));
48         assert(x.length == n - key.get - 1);
49     }
50 
51     assert(x.length == 0);
52 
53     x.clear();
54     assert(x.length == 0);
55 }
56 
57 X testDup(X)(scope ref X x, size_t n)
58 {
59     typeof(return) y = x.dup;
60 
61     assert(x._store.ptr !is y._store.ptr);
62     assert(x.length == y.length);
63     assert(y.length == n);
64     // non-symmetric algorithm so both are needed
65     assert(y == x);
66     assert(x == y);
67 
68     static if (X.hasValue)
69     {
70         assert(equal(x.byKey,
71                      y.byKey));
72         assert(equal(x.byValue,
73                      y.byValue));
74         assert(equal(x.byKeyValue,
75                      y.byKeyValue));
76     }
77     else
78     {
79         assert(equal(x.byElement,
80                      y.byElement));
81     }
82 
83     debug static assert(!__traits(compiles, { const _ = x < y; })); // no ordering
84 
85     return y;
86 }
87 
88 alias NullableUlong = Nullable!(ulong, ulong.max);
89 
90 static class SomeSimpleClass
91 {
92     @safe pure nothrow @nogc
93     this(ulong value)
94     {
95         this._value = value;
96     }
97 
98     @safe pure nothrow @nogc
99     ulong get() const
100     {
101         return _value;
102     }
103 
104     @property void toString(scope void delegate(scope const(char)[]) sink) const
105     {
106         import std.format : formattedWrite;
107         sink.formattedWrite(typeof(this).stringof, "(%s)", _value);
108     }
109 
110     @property bool opEquals(const scope typeof(this) rhs) const
111     {
112         return _value == rhs._value;
113     }
114 
115     private ulong _value;
116 }
117 
118 debug static assert(mustAddGCRange!string);
119 
120 foreach (K; AliasSeq!(SomeSimpleClass,
121                       NullableUlong))
122 {
123     foreach (V; AliasSeq!(string, int, void))
124     {
125         alias X = OpenHashMap!(K, V, FNV!(64, true));
126 
127         auto k11 = make!K(11);
128         auto k12 = make!K(12);
129         auto k13 = make!K(13);
130 
131         static if (!X.hasValue)
132         {
133             auto x = X.withElements([k11, k12, k13].s);
134 
135             import std.algorithm : count;
136 
137             // ByLvalueElement
138             auto xr = x.byElement;
139 
140             alias R = typeof(xr);
141             import std.range.primitives : isInputRange;
142             import std.traits : ReturnType;
143             debug static assert(is(typeof(R.init) == R));
144             debug static assert(is(ReturnType!((R xr) => xr.empty) == bool));
145 
146             debug static assert(!__traits(compiles, { xr.front == K.init; })); // always head-const
147             auto f = xr.front;
148             static if (is(K == class))
149             {
150                 debug static assert(is(typeof(f) == K)); // tail-mutable
151             }
152             else
153             {
154                 debug static assert(is(typeof(f) == const(K))); // tail-const
155             }
156 
157             debug static assert(is(typeof((R xr) => xr.front)));
158             debug static assert(!is(ReturnType!((R xr) => xr.front) == void));
159             debug static assert(is(typeof((R xr) => xr.popFront)));
160 
161             debug static assert(isInputRange!(typeof(xr)));
162 
163             assert(x.byElement.count == 3);
164 
165             X y;
166             size_t ix = 0;
167             foreach (ref e; x.byElement)
168             {
169                 assert(x.contains(e));
170                 assert(x.containsUsingLinearSearch(e));
171                 assert(!y.contains(e));
172                 assert(!y.containsUsingLinearSearch(e));
173                 static if (is(K == class))
174                 {
175                     y.insert(cast(K)e); // ugly but ok in tests
176                 }
177                 else
178                 {
179                     y.insert(e);
180                 }
181                 assert(y.contains(e));
182                 assert(y.containsUsingLinearSearch(e));
183                 ix++;
184             }
185 
186             assert(y.byElement.count == 3);
187             assert(x == y);
188 
189             const z = X();
190             assert(z.byElement.count == 0);
191 
192             immutable w = X();
193             assert(w.byElement.count == 0);
194 
195             {
196                 auto xc = X.withElements([k11, k12, k13].s);
197                 assert(xc.length == 3);
198                 assert(xc.contains(k11));
199                 assert(xc.containsUsingLinearSearch(k11));
200 
201                 // TODO http://forum.dlang.org/post/kvwrktmameivubnaifdx@forum.dlang.org
202                 xc.removeAllMatching!(_ => _ == k11);
203 
204                 assert(xc.length == 2);
205                 assert(!xc.contains(k11));
206                 assert(!xc.containsUsingLinearSearch(k11));
207 
208                 xc.removeAllMatching!(_ => _ == k12);
209                 assert(!xc.contains(k12));
210                 assert(!xc.containsUsingLinearSearch(k12));
211                 assert(xc.length == 1);
212 
213                 xc.removeAllMatching!(_ => _ == k13);
214                 assert(!xc.contains(k13));
215                 assert(!xc.containsUsingLinearSearch(k13));
216                 assert(xc.length == 0);
217 
218                 // this is ok
219                 foreach (e; xc.byElement) {}
220             }
221 
222             {               // ByRvalueElement
223                 auto k = X.withElements([k11, k12].s).filtered!(_ => _ != k11).byElement;
224                 debug static assert(isInputRange!(typeof(k)));
225                 assert(k.front == k12);
226 
227                 debug static assert(!__traits(compiles, { k.front = K.init; })); // head-const
228                 static if (is(K == class))
229                 {
230                     debug static assert(is(typeof(k.front) == K)); // tail-mutable
231                 }
232                 else
233                 {
234                     debug static assert(is(typeof(k.front) == const(K))); // tail-const
235                 }
236 
237                 k.popFront();
238                 assert(k.empty);
239             }
240 
241             {
242                 X q;
243                 auto qv = [make!K(11U), make!K(12U), make!K(13U), make!K(14U)].s;
244                 q.insertN(qv[]);
245                 foreach (e; qv[])
246                 {
247                     assert(q.contains(e));
248                     assert(q.containsUsingLinearSearch(e));
249                 }
250                 q.clear();
251                 assert(q.empty);
252             }
253         }
254 
255         static if (is(V == string))
256         {
257             debug static assert(mustAddGCRange!V);
258             debug static assert(mustAddGCRange!(V[1]));
259             debug static assert(mustAddGCRange!(X.T));
260         }
261 
262         auto x1 = X();            // start empty
263 
264         // fill x1
265 
266         import std.array : Appender;
267         Appender!(K[]) keys;
268 
269         foreach (immutable key_; 0 .. n)
270         {
271             auto key = make!K(key_);
272             keys.put(key);
273 
274             // create elements
275             static if (X.hasValue)
276             {
277                 auto value = V.init;
278                 auto element = X.ElementType(key, value);
279             }
280             else
281             {
282                 // no assignment because Nullable.opAssign may leave rhs in null state
283                 auto element = key;
284             }
285 
286             assert(key !in x1);
287 
288             assert(x1.length == key.get);
289             assert(x1.insert(element) == X.InsertionStatus.added);
290             assert(x1.length == key.get + 1);
291 
292             static if (X.hasValue)
293             {
294                 import std.conv : to;
295                 auto e2 = X.ElementType(key, (42 + key_).to!V);
296                 assert(x1.insert(e2) == X.InsertionStatus.modified);
297                 assert(x1.contains(key));
298                 assert(x1.get(key, V.init) == (42 + key_).to!V);
299 
300                 assert(x1.remove(key));
301                 assert(!x1.contains(key));
302 
303                 x1[key] = value; // restore value
304                 assert(x1.contains(key));
305             }
306 
307             assert(x1.length == key.get + 1);
308 
309             const hitPtr = key in x1;
310             static if (X.hasValue)
311             {
312                 assert(hitPtr && *hitPtr == value);
313             }
314             else
315             {
316                 assert(hitPtr && *hitPtr is key);
317             }
318 
319             auto status = x1.insert(element);
320             assert(status == X.InsertionStatus.unmodified);
321             static if (X.hasValue)
322             {
323                 assert(x1.insert(key, value) == X.InsertionStatus.unmodified);
324             }
325             assert(x1.length == key.get + 1);
326 
327             assert(key in x1);
328         }
329 
330         static if (X.hasValue)
331         {
332             import nxt.dynamic_array : Array = DynamicArray;
333             Array!(X.ElementType) a1; // remember the keys
334 
335             foreach (const ref key; x1.byKey)
336             {
337                 auto keyPtr = key in x1;
338                 assert(keyPtr);
339                 a1 ~= X.ElementType(cast(K)key, (*keyPtr));
340             }
341 
342             assert(x1.length == a1.length);
343 
344             foreach (ae; a1[])
345             {
346                 auto keyPtr = ae.key in x1;
347                 assert(keyPtr);
348                 assert((*keyPtr) is ae.value);
349             }
350         }
351 
352         assert(x1.length == n);
353 
354         auto x2 = testDup(x1, n);
355 
356         testEmptyAll!(K, V)(x1, n, keys.data);
357 
358         testEmptyAll!(K, V)(x2, n, keys.data); // should be not affected by emptying of x1
359     }
360 }
version(showEntries) dbg();
import std.typecons : Nullable;
import nxt.digestx.fnv : FNV;

alias X = OpenHashMap!(Nullable!(size_t, size_t.max), size_t, FNV!(64, true));
import nxt.dynamic_array : Array = DynamicArray;
X x;
// TODO these segfault:
// TODO auto a = Array!(X.KeyType).withElementsOfRange_untested(x.byKey); // l-value byKey
// TODO auto b = Array!(X.KeyType).withElementsOfRange_untested(X().byKey); // r-value byKey

manual Nullable type

import nxt.digestx.fnv : FNV;

static class Zing
{
    @safe pure nothrow @nogc:
    this(ulong value) { this._value = value; }
    private ulong _value;
}
debug static assert(isNullable!Zing);

enum Alt
{
    unknown,
    a,
    b,
    c,
    d
}

struct ZingRelation
{
    Zing zing;
    Alt alts;

    alias nullifier = zing;
    static immutable nullValue = typeof(this).init;

    bool opEquals(const scope typeof(this) that) const @safe pure nothrow @nogc
    {
        return (this.zing is that.zing &&
                this.alts == that.alts);
    }
}
debug static assert(isNullable!ZingRelation);

alias X = OpenHashSet!(ZingRelation, FNV!(64, true));
debug static assert(X.sizeof == 32); // TODO fix hole handling and change to 24
X x;

scope e = ZingRelation(new Zing(42), Alt.init);

assert(!x.contains(e));
assert(!x.containsUsingLinearSearch(e));
assert(x.insert(e) == X.InsertionStatus.added);
assert(x.contains(e));
assert(x.containsUsingLinearSearch(e));

abstract class value type

static abstract class Zing
{
    @safe pure nothrow @nogc:
}
static class Node : Zing
{
    @safe pure nothrow @nogc:
}

alias X = OpenHashSet!(Zing);
X x;

const Zing cz = new Node();
x.insert(cz);               // ok to insert const

Zing z = new Node();
x.insert(z); // ok to insert mutable because hashing is on address by default

class type with default hashing

1 static class Base
2 {
3     static size_t dtorCount = 0; // number of calls to this destructor
4 @safe nothrow @nogc:
5     ~this() @nogc { dtorCount += 1; }
6 pure:
7     this(ulong value) { this._value = value; }
8     @property bool opEquals(const scope typeof(this) rhs) const
9     {
10         return _value == rhs._value;
11     }
12     override hash_t toHash() const
13     {
14         return hashOf(_value);
15     }
16     private ulong _value;
17 }
18 
19 /** Node containing same data members but different type. */
20 static class Node : Base
21 {
22     @safe pure nothrow @nogc:
23     this(ulong value) { super(value);  }
24 }
25 debug static assert(is(Node : Base));
26 
27 import nxt.hash_functions : hashOfPolymorphic; // neede to separate hash of `Base(N)` from `Node(N)`
28 alias X = OpenHashSet!(Base, hashOfPolymorphic, "a && b && (typeid(a) is typeid(b)) && a.opEquals(b)");
29 debug static assert(X.sizeof == 24);
30 X x;
31 
32 // top-class
33 scope b42 = new Base(42);
34 assert(!x.contains(b42));
35 assert(!x.containsUsingLinearSearch(b42));
36 assert(x.insert(b42) == X.InsertionStatus.added);
37 assert(x.contains(b42));
38 assert(x.containsUsingLinearSearch(b42));
39 assert(x.tryGetElementFromCtorParams!Base(42) !is null);
40 assert(Base.dtorCount == 1);
41 assert(x.tryGetElementFromCtorParams!Base(42)._value == 42);
42 assert(Base.dtorCount == 2);
43 assert(x.tryGetElementFromCtorParams!Base(41) is null);
44 assert(Base.dtorCount == 3);
45 
46 // top-class
47 scope b43 = new Base(43);
48 assert(!x.contains(b43));
49 assert(!x.containsUsingLinearSearch(b43));
50 assert(x.insert(b43) == X.InsertionStatus.added);
51 assert(x.contains(b43));
52 assert(x.containsUsingLinearSearch(b43));
53 assert(x.tryGetElementFromCtorParams!Base(43) !is null);
54 assert(Base.dtorCount == 4);
55 assert(x.tryGetElementFromCtorParams!Base(43)._value == 43);
56 assert(Base.dtorCount == 5);
57 
58 // sub-class
59 assert(x.tryGetElementFromCtorParams!Node(42) is null);
60 assert(Base.dtorCount == 6);
61 immutable n42 = new Node(42);
62 assert(!x.contains(n42));     // mustn't equal to `b42`
63 assert(!x.containsUsingLinearSearch(n42)); // mustn't equal to `b42`
64 assert(x.insert(n42) == X.InsertionStatus.added); // added as separate type
65 assert(x.contains(n42));
66 assert(x.containsUsingLinearSearch(n42));
67 assert(x.tryGetElementFromCtorParams!Node(42) !is null);
68 assert(Base.dtorCount == 7);
69 assert(x.tryGetElementFromCtorParams!Node(42)._value == 42);
70 assert(Base.dtorCount == 8);
71 
72 assert(hashOf(b42) == hashOf(n42));
73 
74 // sub-class
75 assert(x.tryGetElementFromCtorParams!Node(43) is null);
76 assert(Base.dtorCount == 9);
77 auto n43 = new Node(43);
78 assert(!x.contains(n43));     // mustn't equal to `b43`
79 assert(!x.containsUsingLinearSearch(n43)); // mustn't equal to `b43`
80 assert(x.insert(n43) == X.InsertionStatus.added); // added as separate type
81 assert(x.contains(n43));
82 assert(x.containsUsingLinearSearch(n43));
83 assert(x.tryGetElementFromCtorParams!Node(43) !is null);
84 assert(Base.dtorCount == 10);
85 assert(x.tryGetElementFromCtorParams!Node(43)._value == 43);
86 assert(Base.dtorCount == 11);
87 
88 assert(hashOf(b43) == hashOf(n43));

enumeration key

import nxt.digestx.fnv : FNV;

enum Alt
{
    nullValue,              // trait
    a, b, c, d
}
alias X = OpenHashSet!(Alt, FNV!(64, true));
X x;
assert(!x.contains(Alt.a));

assert(x.insert(Alt.a) == X.InsertionStatus.added);

assert(x.contains(Alt.a));
assert(x.containsUsingLinearSearch(Alt.a));
assert(!x.contains(Alt.b));
assert(!x.contains(Alt.c));
assert(!x.contains(Alt.d));
assert(!x.containsUsingLinearSearch(Alt.b));
assert(!x.containsUsingLinearSearch(Alt.c));
assert(!x.containsUsingLinearSearch(Alt.d));

assert(x.remove(Alt.a));
assert(!x.contains(Alt.a));
assert(!x.containsUsingLinearSearch(Alt.a));
import nxt.digestx.fnv : FNV;
static struct Rel
{
    static immutable nullValue = typeof(this).init;
    string name;            // relation name. WARNING compiler crashes when qualified with `package`
}
alias X = OpenHashSet!(Rel, FNV!(64, true));
X x;
foreach (const i; 0 .. 100)
{
    const char[1] ch = ['a' + i];
    assert(!x.contains(Rel(ch.idup)));
    assert(!x.containsUsingLinearSearch(Rel(ch.idup)));
    x.insert(Rel(ch.idup));
    assert(x.contains(Rel(ch.idup)));
    /* TODO assert(x.containsUsingLinearSearch(Rel(ch.idup))); */
}

SSOString as set key type

1 import nxt.sso_string : SSOString;
2 import nxt.digestx.fnv : FNV;
3 
4 alias K = SSOString;
5 static assert(isHoleable!K);
6 alias X = OpenHashSet!(K, FNV!(64, true));
7 const n = 100;
8 
9 X a;
10 foreach (const i; 0 .. n)
11 {
12     const char[1] ch = ['a' + i];
13     const k = K(ch);        // @nogc
14 
15     assert(!a.contains(k));
16     assert(!a.containsUsingLinearSearch(k));
17 
18     assert(a.insert(K(ch)) == X.InsertionStatus.added);
19     // TODO assert(a.insertAndReturnElement(K(ch)) == k);
20     assert(a.contains(k));
21     assert(a.containsUsingLinearSearch(k));
22 
23     assert(a.remove(k));
24     assert(!a.contains(k));
25     assert(a.insert(K(ch)) == X.InsertionStatus.added);
26 
27     assert(a.remove(ch[]));
28     assert(!a.contains(k));
29     assert(a.insert(K(ch)) == X.InsertionStatus.added);
30 }
31 
32 X b;
33 foreach (const i; 0 .. n)
34 {
35     const char[1] ch = ['a' + (n - 1 - i)];
36     const k = K(ch);        // @nogc
37 
38     assert(!b.contains(k));
39     assert(!b.containsUsingLinearSearch(k));
40 
41     assert(b.insert(K(ch)) == X.InsertionStatus.added);
42     // TODO assert(b.insertAndReturnElement(K(ch)) == k);
43 
44     assert(b.contains(k));
45     assert(b.containsUsingLinearSearch(k));
46 
47     assert(b.remove(k));
48     assert(!b.contains(k));
49 
50     assert(b.insert(K(ch)) == X.InsertionStatus.added);
51 }
52 
53 assert(a == b);
54 
55 const us = K("_");
56 assert(!a.contains(us));
57 a ~= us;
58 assert(a.contains(us));

test opIndexOpAssign

import nxt.sso_string : SSOString;
import nxt.digestx.fnv : FNV;

alias K = SSOString;
alias V = long;
alias X = OpenHashMap!(K, V, FNV!(64, true));

X x;

const a = K("a");
const b = K("b");

x[a] = 17;
assert(x[a] == 17);

x[a] += 10;                 // opIndexOpAssign!("+=") with existing key
assert(x[a] == 27);

x[b] += 10;                 // opIndexOpAssign!("+=") with non-existing key
assert(x[b] == 10);

x[b] *= 10;                 // opIndexOpAssign!("*=") with non-existing key
assert(x[b] == 100);

assert(x.length == 2);

assert(x.contains(a));
assert(x.contains(a[]));
assert(a in x);
assert(a[] in x);

assert(x.contains(b));
assert(x.contains(b[]));
assert(b in x);
assert(b[] in x);

const c = K("c");
assert(!x.contains(c));
assert(!x.contains(c[]));
assert(c !in x);
assert(c[] !in x);

use prime numbers as capacity

import nxt.address : Address;
alias K = Address;
alias V = size_t;
enum bool usePrimeCapacity = false; // TODO enable
alias M = OpenHashMap!(Address, V,
                       hashOf,
                       defaultKeyEqualPredOf!K,
                       Mallocator.instance,
                       false,
                       true,
                       usePrimeCapacity);
M x;

SSOString as map key type

1 import nxt.sso_string : SSOString;
2 import nxt.digestx.fnv : FNV;
3 alias K = SSOString;
4 alias V = long;
5 alias X = OpenHashMap!(K, V, FNV!(64, true));
6 const n = 100;
7 
8 immutable default_k = K("miss");
9 
10 X a;
11 
12 // insert all
13 foreach (const i; 0 .. n)
14 {
15     const char[1] ch = ['a' + i];
16     const k = K(ch);        // @nogc
17     assert(k[] == ch[]);
18 
19     assert(!a.contains(k));
20     assert(!a.contains(ch[]));                          // @nogc
21     assert(a.getKeyRef(k, default_k)[] is default_k[]); // on miss use `default_k`
22     // TODO assert(a.getKeyRef(ch, default_k)[] is default_k[]); // on miss use `default_k`
23 
24     a[k] = V.init;
25 
26     assert(a.contains(k));
27     assert(a.contains(ch[]));                    // @nogc
28     assert(a.getKeyRef(k, default_k)[] !is k[]); // on hit doesn't use `default_k`
29     assert(a.getKeyRef(k, default_k)[] == ch);
30     // TODO assert(a.getKeyRef(ch, default_k)[] !is k[]); // on hit doesn't use `default_k`
31     // assert(a.getKeyRef(ch, default_k)[] == ch);
32 }
33 assert(a.length == n);
34 
35 // remove all
36 foreach (const i; 0 .. n)
37 {
38     const char[1] ch = ['a' + i];
39     const k = K(ch);        // @nogc
40     assert(a.contains(k));
41     assert(a.remove(k));
42     assert(!a.contains(k));
43 }
44 assert(a.length == 0);
45 
46 // insert all again
47 foreach (const i; 0 .. n)
48 {
49     const char[1] ch = ['a' + i];
50     const k = K(ch);        // @nogc
51     assert(k[] == ch[]);
52 
53     assert(!a.contains(k));
54     assert(!a.contains(ch[]));                          // @nogc
55     assert(a.getKeyRef(k, default_k)[] is default_k[]); // on miss use `default_k`
56     // TODO assert(a.getKeyRef(ch, default_k)[] is default_k[]); // on miss use `default_k`
57 
58     a[k] = V.init;
59 }
60 assert(a.length == n);
61 
62 X b;
63 foreach (const i; 0 .. n)
64 {
65     const char[1] ch = ['a' + (n - 1 - i)];
66     const k = K(ch);        // @nogc
67 
68     assert(!b.contains(k));
69 
70     b[k] = V.init;
71 
72     assert(b.contains(k));
73 }
74 
75 assert(a == b);

Meta