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,
124                           int,
125                           void))
126     {
127         alias X = OpenHashMap!(K, V, FNV!(64, true));
128 
129         auto k11 = make!K(11);
130         auto k12 = make!K(12);
131         auto k13 = make!K(13);
132 
133         static if (!X.hasValue)
134         {
135             auto x = X.withElements([k11, k12, k13].s);
136 
137             import std.algorithm : count;
138 
139             // ByLvalueElement
140             auto xr = x.byElement;
141 
142             alias R = typeof(xr);
143             import std.range.primitives : isInputRange;
144             import std.traits : ReturnType;
145             debug static assert(is(typeof(R.init) == R));
146             debug static assert(is(ReturnType!((R xr) => xr.empty) == bool));
147 
148             debug static assert(!__traits(compiles, { xr.front == K.init; })); // always head-const
149             auto f = xr.front;
150             static if (is(K == class))
151             {
152                 debug static assert(is(typeof(f) == K)); // tail-mutable
153             }
154             else
155             {
156                 debug static assert(is(typeof(f) == const(K))); // tail-const
157             }
158 
159             debug static assert(is(typeof((R xr) => xr.front)));
160             debug static assert(!is(ReturnType!((R xr) => xr.front) == void));
161             debug static assert(is(typeof((R xr) => xr.popFront)));
162 
163             debug static assert(isInputRange!(typeof(xr)));
164 
165             assert(x.byElement.count == 3);
166 
167             X y;
168             size_t ix = 0;
169             foreach (ref e; x.byElement)
170             {
171                 assert(x.contains(e));
172                 assert(x.containsUsingLinearSearch(e));
173                 assert(!y.contains(e));
174                 assert(!y.containsUsingLinearSearch(e));
175                 static if (is(K == class))
176                 {
177                     y.insert(cast(K)e); // ugly but ok in tests
178                 }
179                 else
180                 {
181                     y.insert(e);
182                 }
183                 assert(y.contains(e));
184                 assert(y.containsUsingLinearSearch(e));
185                 ix++;
186             }
187 
188             assert(y.byElement.count == 3);
189             assert(x == y);
190 
191             const z = X();
192             assert(z.byElement.count == 0);
193 
194             immutable w = X();
195             assert(w.byElement.count == 0);
196 
197             {
198                 auto xc = X.withElements([k11, k12, k13].s);
199                 assert(xc.length == 3);
200                 assert(xc.contains(k11));
201                 assert(xc.containsUsingLinearSearch(k11));
202 
203                 // TODO http://forum.dlang.org/post/kvwrktmameivubnaifdx@forum.dlang.org
204                 xc.removeAllMatching!(_ => _ == k11);
205 
206                 assert(xc.length == 2);
207                 assert(!xc.contains(k11));
208                 assert(!xc.containsUsingLinearSearch(k11));
209 
210                 xc.removeAllMatching!(_ => _ == k12);
211                 assert(!xc.contains(k12));
212                 assert(!xc.containsUsingLinearSearch(k12));
213                 assert(xc.length == 1);
214 
215                 xc.removeAllMatching!(_ => _ == k13);
216                 assert(!xc.contains(k13));
217                 assert(!xc.containsUsingLinearSearch(k13));
218                 assert(xc.length == 0);
219 
220                 // this is ok
221                 foreach (e; xc.byElement) {}
222             }
223 
224             {               // ByRvalueElement
225                 auto k = X.withElements([k11, k12].s).filtered!(_ => _ != k11).byElement;
226                 debug static assert(isInputRange!(typeof(k)));
227                 assert(k.front == k12);
228 
229                 debug static assert(!__traits(compiles, { k.front = K.init; })); // head-const
230                 static if (is(K == class))
231                 {
232                     debug static assert(is(typeof(k.front) == K)); // tail-mutable
233                 }
234                 else
235                 {
236                     debug static assert(is(typeof(k.front) == const(K))); // tail-const
237                 }
238 
239                 k.popFront();
240                 assert(k.empty);
241             }
242 
243             {
244                 X q;
245                 auto qv = [make!K(11U), make!K(12U), make!K(13U), make!K(14U)].s;
246                 q.insertN(qv[]);
247                 foreach (e; qv[])
248                 {
249                     assert(q.contains(e));
250                     assert(q.containsUsingLinearSearch(e));
251                 }
252                 q.clear();
253                 assert(q.empty);
254             }
255         }
256 
257         static if (is(V == string))
258         {
259             debug static assert(mustAddGCRange!V);
260             debug static assert(mustAddGCRange!(V[1]));
261             debug static assert(mustAddGCRange!(X.T));
262         }
263 
264         auto x1 = X();            // start empty
265 
266         // fill x1
267 
268         import std.array : Appender;
269         Appender!(K[]) keys;
270 
271         foreach (immutable key_; 0 .. n)
272         {
273             auto key = make!K(key_);
274             keys.put(key);
275 
276             // create elements
277             static if (X.hasValue)
278             {
279                 auto value = V.init;
280                 auto element = X.ElementType(key, value);
281             }
282             else
283             {
284                 // no assignment because Nullable.opAssign may leave rhs in null state
285                 auto element = key;
286             }
287 
288             assert(key !in x1);
289 
290             assert(x1.length == key.get);
291             assert(x1.insert(element) == X.InsertionStatus.added);
292             assert(x1.length == key.get + 1);
293 
294             static if (X.hasValue)
295             {
296                 import std.conv : to;
297                 auto e2 = X.ElementType(key, (42 + key_).to!V);
298                 assert(x1.insert(e2) == X.InsertionStatus.modified);
299                 assert(x1.contains(key));
300                 assert(x1.get(key, V.init) == (42 + key_).to!V);
301 
302                 assert(x1.remove(key));
303                 assert(!x1.contains(key));
304 
305                 x1[key] = value; // restore value
306                 assert(x1.contains(key));
307             }
308 
309             assert(x1.length == key.get + 1);
310 
311             const hitPtr = key in x1;
312             static if (X.hasValue)
313             {
314                 assert(hitPtr && *hitPtr == value);
315             }
316             else
317             {
318                 assert(hitPtr && *hitPtr is key);
319             }
320 
321             auto status = x1.insert(element);
322             assert(status == X.InsertionStatus.unmodified);
323             static if (X.hasValue)
324             {
325                 assert(x1.insert(key, value) == X.InsertionStatus.unmodified);
326             }
327             assert(x1.length == key.get + 1);
328 
329             assert(key in x1);
330         }
331 
332         static if (X.hasValue)
333         {
334             import nxt.dynamic_array : Array = DynamicArray;
335             Array!(X.ElementType) a1; // remember the keys
336 
337             foreach (const ref key; x1.byKey)
338             {
339                 auto keyPtr = key in x1;
340                 assert(keyPtr);
341                 a1 ~= X.ElementType(cast(K)key, (*keyPtr));
342             }
343 
344             assert(x1.length == a1.length);
345 
346             foreach (ae; a1[])
347             {
348                 auto keyPtr = ae.key in x1;
349                 assert(keyPtr);
350                 assert((*keyPtr) is ae.value);
351             }
352         }
353 
354         assert(x1.length == n);
355 
356         auto x2 = testDup(x1, n);
357 
358         testEmptyAll!(K, V)(x1, n, keys.data);
359 
360         testEmptyAll!(K, V)(x2, n, keys.data); // should be not affected by emptying of x1
361     }
362 }
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