Best Way to Pass Template Typed Alias Parameters for Functions?
Vijay Nayar
madric at gmail.com
Sun Dec 23 18:53:15 UTC 2018
On Sunday, 23 December 2018 at 18:31:24 UTC, Alex wrote:
> On Sunday, 23 December 2018 at 18:13:25 UTC, Vijay Nayar wrote:
>> For example, if you have a const function in your container
>> like "T find() const", and this function needs to use that
>> comparator, then you're out of luck because the compiler
>> doesn't know that the comparator function is const and will
>> not modify the objects being compared.
>>
>> Last time I ran into this problem, my solution was simply to
>> give up on const. But now I'm running into it again and trying
>> to think through it again before giving up again.
>
> Hm... still not sure... ;)
> This would compile and run:
>
> ´´´
> import std.experimental.all;
>
> size_t myHashFunction(int a) { return cast(size_t) a; }
>
> void main()
> {
> auto b = new B!(int, myHashFunction);
> b.arr = 42.iota.array;
> assert(b.find == 1);
> }
>
> class B(T, alias HashF)
> {
> T[] arr;
>
> T find() const
> {
> foreach(el; arr)
> {
> if(HashF(el))
> {
> return el;
> }
> }
> assert(0);
> }
> }
> ´´´
You're right, it does compile. I'm a bit surprised. I wonder if
this is a relatively recent improvement in the language, because
last time I ran into this I had no such luck. But after seeing
that your example did work, I figured one could try to get the
best of both worlds by using a strongly-typed wrapper function in
one's class. So far it seems to work:
import std.traits;
class A(KeyT, alias HashF) {
// Strongly-typed wrapper around template value parameter
'HashF'.
static size_t hash(in KeyT key) {
return HashF(key);
}
static this() {
static assert(isCallable!HashF, "Hash function is not
callable!");
static assert(Parameters!(HashF).length == 1, "Hash function
must take 1 argument.");
static assert(is(Parameters!(HashF)[0] : const(KeyT)),
"Hash parameter must be const.");
static assert(is(typeof(HashF(KeyT.init)) : size_t),
"Hash function must return size_t type.");
}
KeyT data;
size_t getHash() const {
return hash(data);
}
}
void main() {
auto a = new A!(int, (int a) => cast(size_t) a);
a.data = 5;
a.getHash();
}
More information about the Digitalmars-d-learn
mailing list