A set type implemented as an AA wrapper

mark mark at qtrac.eu
Thu Mar 12 12:36:26 UTC 2020


On Thursday, 12 March 2020 at 11:33:25 UTC, Simen Kjærås wrote:
[snip]
> I'd suggest simply testing if an AA with that key type is valid:
>
>     struct AAset(T) if (is(int[T]))

That's very subtle, but it works.

> As Ferhat points out, you could use opApply for this. There's 
> also the option of implenting the range primitives front, 
> popFront() and empty. However, the easiest solution is the one 
> you've already chosen, combined with alias this:
>
>     struct AAset(T) if (is(int[T])) {
>         // stuffs...
>         auto range() { return set.byKey; }
>         alias range this;
>     }

Again, subtle, and again it works!

> I would also suggest using a template specialization instead of 
> static if and static assert:
>
>     bool opBinaryRight(string op : "in")(T lhs) {
>         return (lhs in set) != null;
>     }

Thanks, you've solved all the issued I had! Here's the complete 
revised code:

struct AAset(T) if (is(int[T])) {
     private {
         alias Unit = void[0];
         enum unit = Unit.init;
         Unit[T] set;
     }
     size_t length() const { return set.length; }
     void add(T item) { set[item] = unit; }
     bool remove(T item) { return set.remove(item); }
     auto range() { return set.byKey; }
     alias range this;
     bool opBinaryRight(string op: "in")(T lhs) {
         return (lhs in set) != null;
     }
}

unittest {
     import std.algorithm: sort;
     import std.array: array;
     import std.range: enumerate;
     import std.stdio: writeln;
     import std.typecons: Tuple;

     writeln("unittest for the aaset library.");
     alias Pair = Tuple!(int, "count", string, "word");
     immutable inputs = [Pair(1, "one"), Pair(2, "two"), Pair(3, 
"three"),
                         Pair(4, "four"), Pair(4, "two"), Pair(5, 
"five"),
                         Pair(6, "six")];
     AAset!string words;
     assert(words.length == 0);
     foreach (pair; inputs) {
         words.add(pair.word);
         assert(words.length == pair.count);
     }
     immutable len = words.length;
     assert(!words.remove("missing"));
     assert(words.remove("one"));
     assert(words.length == len - 1);
     immutable expected = ["five", "four", "six", "three", "two"];
     foreach (i, word; words.array.sort.enumerate)
         assert(word == expected[i]);
     assert("Z" !in words);
     assert("three" in words);
}


More information about the Digitalmars-d-learn mailing list