www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - array of functions/delegates

reply Rumbu <rumbu rumbu.ro> writes:
I am trying to create an array of functions inside a struct.

struct S {
   void f1() {}
   void f2() {}

   alias Func = void function();

  immutable Func[2] = [&f1, &f2]

}

What I got: Error: non-constant expression '&f1'

Tried also with delegates (since I am in a struct context but I 
got: no `this` to create delegate `f1`.

So, is there any way to have an array of functions without adding 
them at runtime?
Dec 23 2019
next sibling parent Alex <sascha.orlov gmail.com> writes:
On Tuesday, 24 December 2019 at 07:37:02 UTC, Rumbu wrote:
 I am trying to create an array of functions inside a struct.

 struct S {
   void f1() {}
   void f2() {}

   alias Func = void function();

  immutable Func[2] = [&f1, &f2]

 }

 What I got: Error: non-constant expression '&f1'

 Tried also with delegates (since I am in a struct context but I 
 got: no `this` to create delegate `f1`.

 So, is there any way to have an array of functions without 
 adding them at runtime?
If you don't need runtime, probably like this: ´´´ import std; void f1(S s) {assert(1);} void f2(S s) {assert(1);} alias field = AliasSeq!(f1, f2); struct S{} void main() { S s; field[0](s); } ´´´ Don't know why UCFS doesn't work in this case though. Maybe, this is also helpful: https://forum.dlang.org/post/mailman.2415.1354291433.5162.digitalmars-d-learn puremagic.com
Dec 24 2019
prev sibling next sibling parent reply Mike Parker <aldacron gmail.com> writes:
On Tuesday, 24 December 2019 at 07:37:02 UTC, Rumbu wrote:
 I am trying to create an array of functions inside a struct.

 struct S {
   void f1() {}
   void f2() {}

   alias Func = void function();

  immutable Func[2] = [&f1, &f2]

 }

 What I got: Error: non-constant expression '&f1'

 Tried also with delegates (since I am in a struct context but I 
 got: no `this` to create delegate `f1`.

 So, is there any way to have an array of functions without 
 adding them at runtime?
This isn't an array of functions you're creating here. A pointer to a member function is *always* a delegate, unless the function is static. Pointers to functions can be known at compile time, so this works: struct S () { static void f1() {} static void f2() {} alias Func = void function(); immutable Func[2] funcs = [&f1, &f2]; } As does this: struct S {} void f1(S s) {} void f2(S s) {} alias Func = immutable(void function()); immutable Func[2] funcs = [cast(Func)&f1, cast(Func)&f2]; Though, it's not clear to me wy the one requires casting the pointer type and the other doesn't.
Dec 24 2019
parent reply MoonlightSentinel <moonlightsentinel disroot.org> writes:
On Tuesday, 24 December 2019 at 10:40:16 UTC, Mike Parker wrote:
 struct S {}
 void f1(S s) {}
 void f2(S s) {}

 alias Func = immutable(void function());

 immutable Func[2] funcs = [cast(Func)&f1, cast(Func)&f2];

 Though, it's not clear to me wy the one requires casting the 
 pointer type and the other doesn't.
Because typeof(&f1) == void function(S)
Dec 24 2019
next sibling parent MoonlightSentinel <moonlightsentinel disroot.org> writes:
On Tuesday, 24 December 2019 at 13:13:12 UTC, MoonlightSentinel 
wrote:
 On Tuesday, 24 December 2019 at 10:40:16 UTC, Mike Parker wrote:
 struct S {}
 void f1(S s) {}
 void f2(S s) {}

 alias Func = immutable(void function());

 immutable Func[2] funcs = [cast(Func)&f1, cast(Func)&f2];

 Though, it's not clear to me wy the one requires casting the 
 pointer type and the other doesn't.
Because typeof(&f1) == void function(S)
Working example without casts using type deduction: import std.stdio: writeln; struct S {} void f1(S s) { writeln("f1"); } void f2(S s) { writeln("f2"); } immutable funcs = [&f1, &f2]; void main() { S s; foreach(f; funcs) { f(s); } }
Dec 24 2019
prev sibling parent Mike Parker <aldacron gmail.com> writes:
On Tuesday, 24 December 2019 at 13:13:12 UTC, MoonlightSentinel 
wrote:
 On Tuesday, 24 December 2019 at 10:40:16 UTC, Mike Parker wrote:
 struct S {}
 void f1(S s) {}
 void f2(S s) {}

 alias Func = immutable(void function());

 immutable Func[2] funcs = [cast(Func)&f1, cast(Func)&f2];

 Though, it's not clear to me wy the one requires casting the 
 pointer type and the other doesn't.
Because typeof(&f1) == void function(S)
Right. I didn't modify the alias declaration when I took the functions out of the struct. I saw the immutable in the error message and thought that was the problem. alias Func = void function(S);
Dec 24 2019
prev sibling parent reply MoonlightSentinel <moonlightsentinel disroot.org> writes:
On Tuesday, 24 December 2019 at 07:37:02 UTC, Rumbu wrote:
 I am trying to create an array of functions inside a struct.

 struct S {
   void f1() {}
   void f2() {}

   alias Func = void function();

  immutable Func[2] = [&f1, &f2]

 }

 What I got: Error: non-constant expression '&f1'

 Tried also with delegates (since I am in a struct context but I 
 got: no `this` to create delegate `f1`.

 So, is there any way to have an array of functions without 
 adding them at runtime?
You can set funcs within the constructor but not as a default initializer because they have to be compile time constants (https://dlang.org/spec/struct.html#default_struct_init) struct S { void f1() {} void f2() {} alias Func = void delegate(); immutable Func[2] funcs; this(bool) { funcs = [&f1, &f2]; } } &f1 creates a delegate which contain a function pointer and the context pointer (struct, closure, ...). In this example the latter contains a pointer to a concrete instance of S which is a usually a runtime value. (https://dlang.org/spec/type.html#delegates)
Dec 24 2019
parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 12/24/19 8:52 AM, MoonlightSentinel wrote:
 On Tuesday, 24 December 2019 at 07:37:02 UTC, Rumbu wrote:
 I am trying to create an array of functions inside a struct.

 struct S {
   void f1() {}
   void f2() {}

   alias Func = void function();

  immutable Func[2] = [&f1, &f2]

 }

 What I got: Error: non-constant expression '&f1'

 Tried also with delegates (since I am in a struct context but I got: 
 no `this` to create delegate `f1`.

 So, is there any way to have an array of functions without adding them 
 at runtime?
You can set funcs within the constructor but not as a default initializer because they have to be compile time constants (https://dlang.org/spec/struct.html#default_struct_init) struct S {     void f1() {}     void f2() {}     alias Func = void delegate();     immutable Func[2] funcs;     this(bool)     {         funcs = [&f1, &f2];     } } &f1 creates a delegate which contain a function pointer and the context pointer (struct, closure, ...). In this example the latter contains a pointer to a concrete instance of S which is a usually a runtime value. (https://dlang.org/spec/type.html#delegates)
Just FYI, doing this is very suspicious. Storing a delegate to a struct means you have a context pointer to that struct. And structs can usually move around freely. Meaning that f1 and f2 are still going to refer to the original struct, even if it has been copied, and even if the struct has been deallocated (i.e. it was on a stack frame that no longer exists). -Steve
Dec 26 2019