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