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









Lodovico Giaretta <lodovico giaretart.net> 