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);
}