digitalmars.D.learn - Retreive method given object, name and arguments
- Michael Coulombe (15/15) Aug 11 2016 Is there a way to implement "getSymbolOfCall" and
- Lodovico Giaretta (8/24) Aug 11 2016 Maybe I'm not understanding correctly, but I think you can use
- ketmar (23/23) Aug 11 2016 On Thursday, 11 August 2016 at 20:27:51 UTC, Michael Coulombe
- ketmar (2/2) Aug 11 2016 On Thursday, 11 August 2016 at 20:41:33 UTC, ketmar wrote:
- ketmar (68/68) Aug 11 2016 On Thursday, 11 August 2016 at 20:27:51 UTC, Michael Coulombe
Is there a way to implement "getSymbolOfCall" and "getDelegateOfCall" such that doit is functionally equivalent to calling the method directly? auto doit(C, string methodName, Args...)(C c, Args args) { alias methodSymbol = getSymbolOfCall!(c, methodName, Args); pragma(msg, hasUDA!(methodSymbol, "my attr")); auto dg = getDelegateOfCall!(c, methodName, Args); return dg(args); } They should deal with getting the right overload, opDispatch-ing, and deducing template arguments from the real argument list to get a concrete delegate pointer. methodSymbol should give access to compile-time introspection like full signature and UDAs. The ability to do this for non-member functions would be cool too, but is beyond my use case.
Aug 11 2016
On Thursday, 11 August 2016 at 20:27:51 UTC, Michael Coulombe wrote:Is there a way to implement "getSymbolOfCall" and "getDelegateOfCall" such that doit is functionally equivalent to calling the method directly? auto doit(C, string methodName, Args...)(C c, Args args) { alias methodSymbol = getSymbolOfCall!(c, methodName, Args); pragma(msg, hasUDA!(methodSymbol, "my attr")); auto dg = getDelegateOfCall!(c, methodName, Args); return dg(args); } They should deal with getting the right overload, opDispatch-ing, and deducing template arguments from the real argument list to get a concrete delegate pointer. methodSymbol should give access to compile-time introspection like full signature and UDAs. The ability to do this for non-member functions would be cool too, but is beyond my use case.Maybe I'm not understanding correctly, but I think you can use string mixins: auto doit(string methodName, C, Args...)(C c, Args args) { mixin("return c." ~ methodName ~ "(args);"); }
Aug 11 2016
On Thursday, 11 August 2016 at 20:27:51 UTC, Michael Coulombe wrote: import std.stdio; struct S { void foo () { writeln("foo()"); } void foo (int n) { writeln("foo(", n, ")"); } } auto doit(string methodName, C, Args...) (C c, Args args) { static if (is(typeof(mixin("c."~methodName~"(args)")))) { mixin("return c."~methodName~"(args);"); } else { throw new Exception("no method '"~methodName~"' in type "~C.stringof); } } void main () { S s; s.doit!"foo"(42); s.doit!"foo"(); s.doit!"oops"(); // this throws } of course, you can replace `static if` with `static assert` to turn it into compile-time error.
Aug 11 2016
On Thursday, 11 August 2016 at 20:41:33 UTC, ketmar wrote: ah, my bad, i missed UDA part of the question. sorry. ;-)
Aug 11 2016
On Thursday, 11 August 2016 at 20:27:51 UTC, Michael Coulombe wrote: here is something for you to play with: import std.stdio; enum CallAllowed0; enum CallAllowed1; struct S { CallAllowed0 void foo () { writeln("foo()"); } CallAllowed1 void foo (int n) { writeln("foo(", n, ")"); } } bool hasGoodMethod(string methodName, UDA, C, Args...) () { import std.traits: hasUDA; bool res = false; alias Identity(T...) = T[0]; foreach (string mem; __traits(allMembers, C)) { static if (mem == methodName) { static if (is(typeof(__traits(getMember, C, mem)))) { alias mx = Identity!(__traits(getMember, C, mem)); foreach (auto t; __traits(getOverloads, C, mem)) { static if (hasUDA!(t, UDA)) { static if (is(typeof((Args args) { auto dg = &t; dg(args); }))) { res = true; break; } } } } } } return res; } auto doit(string methodName, UDA, C, Args...) (C c, Args args) { static if (hasGoodMethod!(methodName, UDA, C, Args)) { mixin("return c."~methodName~"(args);"); } else { static assert(0, "can't call method '"~methodName~"' in type "~C.stringof); } } void main () { S s; version(v0) { s.doit!("foo", CallAllowed0)(42); } else version(v1) { s.doit!("foo", CallAllowed1)(42); } else version(v2) { s.doit!("foo", CallAllowed0)(); } else version(v3) { s.doit!("foo", CallAllowed1)(); } else { static assert(0, "version?"); } } % rdmd -version=v0 z02.d z02.d(47): Error: static assert "can't call method 'foo' in type S" z02.d(55): instantiated from here: doit!("foo", CallAllowed0, S, int) % rdmd -version=v1 z02.d foo(42) % rdmd -version=v2 z02.d foo() % rdmd -version=v3 z02.d z02.d(47): Error: static assert "can't call method 'foo' in type S" z02.d(61): instantiated from here: doit!("foo", CallAllowed1, S)
Aug 11 2016