www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Is using function() in templates possible at all?

reply Sjoerd Nijboer <sjoerdnijboer gmail.com> writes:
I am trying to do a binary insert into my sorted array.
To sort classes and structs I would like to give a delegate `(t) 
=> t.myValue` to sort on that value whitout having to implement 
an interface or specifically declare opCmp for every class I want 
to have sorted.
After all, I might want one group of objects of a given class 
sorted in one way and another group of objects sorted on another 
way depending on the usecase.

expression to sort such list after insertion, and is also usefull 
in other circumstances.

But is it possible in D to do something simular but then pass on 
this Function() during compile time?

something like
`
void main() { SortedList!(Vector3, (v) => v.y) list; }

struct Vector3 { float x, y, z; }

class SortedList(T, int function(T) comparer)
{
	T[] array;
	
	int foo(T t)
	{
		for(int i = 0; i < array.lenght; i++)
		{
			if(comparer(this.otherT) <=  comparer(t))
			{
				//do stuff
				array[i] = t;
			}
		}
	}
}
`
Apr 11 2018
parent reply Alex <sascha.orlov gmail.com> writes:
On Wednesday, 11 April 2018 at 21:07:03 UTC, Sjoerd Nijboer wrote:

 class SortedList(T, int function(T) comparer)
I would say, alias template parameter is your friend. https://dlang.org/spec/template.html#TemplateAliasParameter ´´´ import std.stdio; import std.range; void main() { auto list = new SortedList!(Vector3, v => v.y)(); assert(list.array.empty); list.foo(Vector3.init); } struct Vector3 { float x, y, z; } class SortedList(T, alias comparer) { T[] array; auto foo(T t) { for(int i = 0; i < array.length; i++) { if(comparer(this.array[i]) <= comparer(t)) { //do stuff array[i] = t; } } } } ´´´
Apr 11 2018
parent reply Sjoerd Nijboer <sjoerdnijboer gmail.com> writes:
On Wednesday, 11 April 2018 at 21:29:27 UTC, Alex wrote:
 I would say, alias template parameter is your friend.
 https://dlang.org/spec/template.html#TemplateAliasParameter

 class SortedList(T, alias comparer)
It works, thank you! But just to be shure, there's no way to have this more strongly typed in D so I can enforce that `comparer`is a funciton or delegate with a specific defenition? Right now i'm relying on the template to error on some different place which might not give such a readable error message to the user.
Apr 11 2018
parent reply Nicholas Wilson <iamthewilsonator hotmail.com> writes:
On Wednesday, 11 April 2018 at 22:13:33 UTC, Sjoerd Nijboer wrote:
 On Wednesday, 11 April 2018 at 21:29:27 UTC, Alex wrote:
 I would say, alias template parameter is your friend.
 https://dlang.org/spec/template.html#TemplateAliasParameter

 class SortedList(T, alias comparer)
It works, thank you! But just to be shure, there's no way to have this more strongly typed in D so I can enforce that `comparer`is a funciton or delegate with a specific definition?
There is, with template constraints: class SortedList(T, alias comparer) if(is(typeof(comparer(T.init) : int)) { //... }
Apr 11 2018
parent reply Laurent =?UTF-8?B?VHLDqWd1aWVy?= <laurent.treguier.sink gmail.com> writes:
On Thursday, 12 April 2018 at 00:05:26 UTC, Nicholas Wilson wrote:
 There is, with template constraints:

 class SortedList(T, alias comparer)
     if(is(typeof(comparer(T.init) : int))
 {
     //...
 }
If the function is declared with explicit parameter types: ``` auto list = new SortedList!(Vector3, (Vector3 v) => v.y)(); ``` Then the template guard can even have a full type definition: ``` class SortedList(T, alias comparer) if (is(typeof(comparer) : int function(T))) { //... } ```
Apr 12 2018
parent reply Alex <sascha.orlov gmail.com> writes:
On Thursday, 12 April 2018 at 11:17:01 UTC, Laurent Tréguier 
wrote:
 If the function is declared with explicit parameter types:
There are cool things possible, if the param type is explicitly typed :) ´´´ import std.traits; void main() { auto list = new SortedList!((Vector3 v) => v.y)(); list.foo(Vector3.init); } struct Vector3 { float x, y, z; } class SortedList(alias comparer) if(is(ReturnType!comparer : float)) { alias T = Parameters!comparer[0]; T[] array; auto foo(T t) { // do stuff } } ´´´
Apr 12 2018
parent Laurent =?UTF-8?B?VHLDqWd1aWVy?= <laurent.treguier.sink gmail.com> writes:
On Thursday, 12 April 2018 at 11:53:21 UTC, Alex wrote:
 On Thursday, 12 April 2018 at 11:17:01 UTC, Laurent Tréguier 
 wrote:
 If the function is declared with explicit parameter types:
There are cool things possible, if the param type is explicitly typed :) ´´´ import std.traits; void main() { auto list = new SortedList!((Vector3 v) => v.y)(); list.foo(Vector3.init); } struct Vector3 { float x, y, z; } class SortedList(alias comparer) if(is(ReturnType!comparer : float)) { alias T = Parameters!comparer[0]; T[] array; auto foo(T t) { // do stuff } } ´´´
Getting rid of redundancy. Now that's nice !
Apr 12 2018