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