Defining an alias to an overloaded function
olvy
olvy at olvy.ol
Mon Jan 20 22:02:54 UTC 2020
I'm learning D, and as an exercise, I'm trying to define a
HashSet that would be a wrapper around an associative array with
some dummy value type.
This worked fine until I've tried writing opSlice for this
HashSet in terms of the byKey() function of the AA. I defined my
own internal type that wraps the one returned by byKey and
returned it. However I had to keep byKey's result inside my
internal type, but I couldn't figure out how to name it properly
without getting a compilation error.
The problem is that byKey is overloaded and but I can't figure
out how to convince the compiler to disambiguate between the
overloads.
Another lesser problem is that I have to write "opSlice"
explicitly at the call site instead of using []. But it might
be that the compiler is confused due to failure of parsing the
function.
My aim isn't building a HashSet, the point is learning, here
specifically learning how to convince the compiler to use the
correct byKey overload in this case.
I could also trivially use the AA's keys() function to implement
opSlice. But I like byKey since it exposes just an iterator,
while keys() actually allocates an array which isn't necessary
here.
I'm using dmd 2.089 on my machine.
My code is (also in https://wandbox.org/permlink/zXsf7sQiKDj6zjlJ)
import std;
struct HashSet(T) {
int[T] _dict;
bool add(T val) {
auto prev = val in _dict;
_dict[val] = 0;
return prev is null;
}
bool remove(T val) {
return _dict.remove(val);
}
bool opBinaryRight(string op)(T val) {
static if (op == "in") {
return (val in _dict) !is null;
} else {
static assert(false, "Operator " ~ op ~ " not
implemented");
}
}
import std.traits;
import std.meta;
struct RangeImpl(T) {
// Next line has compilation error since byKey has 2
overloads
alias byKeyAlias = Alias!(byKey!(int[T])(T.init));
ReturnType!(byKeyAlias) keyRange;
// alias byKeyAlias = byKey;
// ReturnType!(byKey!(int[T], T, int)) keyRange;
this(ref int[T] d) {
keyRange = d.byKey();
}
bool empty() const {
return keyRange.empty;
}
ref T front() {
return keyRange.front;
}
void popFront() {
keyRange.popFront();
}
}
// T[] opSlice(T)() {
// return _dict.keys;
// }
RangeImpl!T opSlice(T)() {
return RangeImpl!T(_dict);
}
}
void main()
{
HashSet!long h;
h.add(0);
h.add(1);
if (1 in h) {
writeln("it is");
}
if (h.opSlice!long.all!(nn => nn < 5)) {
writeln("less than 5");
}
}
More information about the Digitalmars-d-learn
mailing list