digitalmars.D - Cannot use function as foreach aggregate.
- Daniel Keep (17/17) Apr 04 2007 So, I've just discovered that you can't use function pointers as the
- Jarrett Billingsley (18/25) Apr 04 2007 I don't know if it's the cleanest but it works well.
- BCS (14/31) Apr 04 2007 I can't help but wonder if this works.
- Lutger (11/24) Apr 04 2007 Perhaps it could be simplified to this:
- Jarrett Billingsley (23/37) Apr 04 2007 Not quite.. you can't alias addresses, and I don't think you can pass
- BCS (25/54) Apr 05 2007 I don't think that will work. It will only allow one delegate per
- Jarrett Billingsley (28/44) Apr 05 2007 Yeah, you're right; I forgot that I didn't use an alias template paramet...
- BCS (21/40) Apr 05 2007 Of course this all only works for statically known functions. If that
- Jarrett Billingsley (3/24) Apr 05 2007 Error: can't convert from void* to a function pointer. Oh well.
- BCS (14/49) Apr 06 2007 OK, I've tested this one on 0.177
- Russell Lewis (13/30) Apr 04 2007 What you give above is the good, general solution, which allows you to
- Downs (5/7) Apr 05 2007 Okay, so it's not the cleanest way, and it's not automatic either, but i...
So, I've just discovered that you can't use function pointers as the aggregate of a foreach. To put it mildly: this sucks. Basically I have a bunch of module-level functions used to iterate over some global state private to that module. So, two questions: 1. Is this a bug? If it's not, why can we use delegates but not function pointers? 2. What's the cleanest way to wrap a function pointer in a delegate? -- Daniel -- int getRandomNumber() { return 4; // chosen by fair dice roll. // guaranteed to be random. } http://xkcd.com/ v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
Apr 04 2007
"Daniel Keep" <daniel.keep.lists gmail.com> wrote in message news:ev07p5$17u9$1 digitalmars.com...So, I've just discovered that you can't use function pointers as the aggregate of a foreach. To put it mildly: this sucks. Basically I have a bunch of module-level functions used to iterate over some global state private to that module. So, two questions: 1. Is this a bug? If it's not, why can we use delegates but not function pointers? 2. What's the cleanest way to wrap a function pointer in a delegate?I don't know if it's the cleanest but it works well. RetType delegate(Args) ToDelegate(RetType, Args...)(RetType function(Args) func) { struct S { RetType function(Args) func; RetType callMe(Args args) { return func(args); } } S* s = new S; s.func = func; return &s.callMe; }
Apr 04 2007
Jarrett Billingsley wrote:"Daniel Keep" <daniel.keep.lists gmail.com> wrote in message news:ev07p5$17u9$1 digitalmars.com...I can't help but wonder if this works. template ToDelegate(RetType, RetType function(Args) func, Args...) { struct S { static S s RetType callMe(Args args) { return func(args); } } alias &S.s.callMe ToDelegate; }So, I've just discovered that you can't use function pointers as the aggregate of a foreach. To put it mildly: this sucks. Basically I have a bunch of module-level functions used to iterate over some global state private to that module. So, two questions: 1. Is this a bug? If it's not, why can we use delegates but not function pointers? 2. What's the cleanest way to wrap a function pointer in a delegate?I don't know if it's the cleanest but it works well.
Apr 04 2007
BCS wrote: > I can't help but wonder if this works.template ToDelegate(RetType, RetType function(Args) func, Args...) { struct S { static S s RetType callMe(Args args) { return func(args); } } alias &S.s.callMe ToDelegate; }Perhaps it could be simplified to this: ReturnType!(typeof(func)) delegate (A) toDelegate(alias func, A = ParameterTypeTuple!(typeof(func)) )() { return ( A args) { return func(args); } ; } But it seems there is a bug with type tuples in delegate literals, which also affects your example. This can be made to work though with string mixins, expanding the tuples to a parameter list.
Apr 04 2007
"BCS" <BCS pathlink.com> wrote in message news:ev0i44$2io$5 digitalmars.com...Jarrett Billingsley wrote: I can't help but wonder if this works. template ToDelegate(RetType, RetType function(Args) func, Args...) { struct S { static S s RetType callMe(Args args) { return func(args); } } alias &S.s.callMe ToDelegate; }Not quite.. you can't alias addresses, and I don't think you can pass function pointers as template arguments (though I might be wrong). Though using your idea of a single static instance of the struct, my function can then become: RetType delegate(Args) ToDelegate(RetType, Args...)(RetType function(Args) func) { struct S { static S s; static RetType function(Args) func; RetType callMe(Args args) { return func(args); } } S.func = func; return &S.s.callMe; } Which is pretty sweet, as it no longer requires a heap allocation with each call.
Apr 04 2007
Jarrett Billingsley wrote:Not quite.. you can't alias addresses, and I don't think you can pass function pointers as template arguments (though I might be wrong). Though using your idea of a single static instance of the struct, my function can then become: RetType delegate(Args) ToDelegate(RetType, Args...)(RetType function(Args) func) { struct S { static S s; static RetType function(Args) func; RetType callMe(Args args) { return func(args); } } S.func = func; return &S.s.callMe; } Which is pretty sweet, as it no longer requires a heap allocation with each call.I don't think that will work. It will only allow one delegate per function type. int foo(int i){return 1;} int bar(int i){return 2;} auto a = ToDelegate!(int, int)(foo); auto b = ToDelegate!(int, int)(bar); // stomps on a; a(1); // should return 2 when 1 is expected also it occurs to me that there is no reason that the addressOf is needed. If functions as args works (I think it does) then this should work: template ToDelegate(RetType, RetType function(Args) func, Args...) { struct S { static S s RetType callMe(Args args) { return func(args); } } alias S.s.callMe ToDelegate; } if that doesn't work than this might: template ToDelegate(RetType, alias func, Args...) but it might have problem with overloaded functions.
Apr 05 2007
"BCS" <BCS pathlink.com> wrote in message news:ev379f$1ccm$1 digitalmars.com...I don't think that will work. It will only allow one delegate per function type.Yeah, you're right; I forgot that I didn't use an alias template parameter so it would be based on signature, not name.also it occurs to me that there is no reason that the addressOf is needed. If functions as args works (I think it does) then this should work: template ToDelegate(RetType, RetType function(Args) func, Args...) { struct S { static S s RetType callMe(Args args) { return func(args); } } alias S.s.callMe ToDelegate; }You can't alias expressions. It has to be a function: template ToDelegate(alias func) { ReturnType!(func) delegate(ParameterTypeTuple!(func)) ToDelegate() { struct S { static S s; ReturnType!(func) callMe(ParameterTypeTuple!(func) args) { return func(args); } } return &S.s.callMe; } } ... int foo(int i){return 1;} int bar(int i){return 2;} ... auto a = ToDelegate!(foo); auto b = ToDelegate!(bar); writefln(a(1)); writefln(a(2));
Apr 05 2007
Jarrett Billingsley wrote:You can't alias expressions. It has to be a function: template ToDelegate(alias func) { ReturnType!(func) delegate(ParameterTypeTuple!(func)) ToDelegate() { struct S { static S s; ReturnType!(func) callMe(ParameterTypeTuple!(func) args) { return func(args); } } return &S.s.callMe; } }Of course this all only works for statically known functions. If that isn't the case then the original solution is needed. OTOH this might work template ToDelegate(alias func) { ReturnType!(func) delegate(ParameterTypeTuple!(func)) ToDelegate() { struct S { ReturnType!(func) callMe(ParameterTypeTuple!(func) args) { return(cast(typeof(func))cast(void*)this)(args); } } return &((cast(S*)cast(void*)&func).callMe); } } I'd have to play with it but the same thing could be done for a dynamic pointer just with a few things moved around. Ohh, I'd so fire anyone who tried to get me to pay them for writing that.
Apr 05 2007
"BCS" <BCS pathlink.com> wrote in message news:ev45id$94v$1 digitalmars.com...Jarrett Billingsley wrote: Of course this all only works for statically known functions. If that isn't the case then the original solution is needed. OTOH this might work template ToDelegate(alias func) { ReturnType!(func) delegate(ParameterTypeTuple!(func)) ToDelegate() { struct S { ReturnType!(func) callMe(ParameterTypeTuple!(func) args) { return(cast(typeof(func))cast(void*)this)(args); } } return &((cast(S*)cast(void*)&func).callMe); } } I'd have to play with it but the same thing could be done for a dynamic pointer just with a few things moved around. Ohh, I'd so fire anyone who tried to get me to pay them for writing that.Error: can't convert from void* to a function pointer. Oh well.
Apr 05 2007
Jarrett Billingsley wrote:"BCS" <BCS pathlink.com> wrote in message news:ev45id$94v$1 digitalmars.com...OK, I've tested this one on 0.177 (Yes, I need to update this system :-b) R delegate(Args) ToDelegate(R, Args...)(R function(Args) func) { struct S { void callMe(Args args) { return (cast(R function(Args))cast(void*)this)(args); } } return &((cast(S*)cast(void*)func).callMe); }Jarrett Billingsley wrote: Of course this all only works for statically known functions. If that isn't the case then the original solution is needed. OTOH this might work template ToDelegate(alias func) { ReturnType!(func) delegate(ParameterTypeTuple!(func)) ToDelegate() { struct S { ReturnType!(func) callMe(ParameterTypeTuple!(func) args) { return(cast(typeof(func))cast(void*)this)(args); } } return &((cast(S*)cast(void*)&func).callMe); } } I'd have to play with it but the same thing could be done for a dynamic pointer just with a few things moved around. Ohh, I'd so fire anyone who tried to get me to pay them for writing that.Error: can't convert from void* to a function pointer. Oh well.
Apr 06 2007
Jarrett Billingsley wrote:RetType delegate(Args) ToDelegate(RetType, Args...)(RetType function(Args) func) { struct S { RetType function(Args) func; RetType callMe(Args args) { return func(args); } } S* s = new S; s.func = func; return &s.callMe; }What you give above is the good, general solution, which allows you to save the resulting delegate, or return it from the function, or whatever. But in cases where the delegate won't be used outside of the current function, it's simpler to use a delegate literal: void myFunc() { int function(int delegate(inout Type)) myAggregateFunc = <whatever>; int delegate(int delegate(inout Type)) myAggregateDelegate = delegate int(int delegate(inout Type) dg) { return myAggregateFunc(dg); } foreach(Type myVar; myAggregateDelegate) { <body> } }
Apr 04 2007
Daniel Keep wrote:2. What's the cleanest way to wrap a function pointer in a delegate?Okay, so it's not the cleanest way, and it's not automatic either, but it's easy as heck. import std.stdio; bool test(int e, float f) { return true; } void main() { auto dg=(int e, float f) { return test(e, f); }; dg(4, 3.14159); writefln(typeid(typeof(dg))); }
Apr 05 2007