Function Pointer Challenge
Jonathan Marler via Digitalmars-d
digitalmars-d at puremagic.com
Wed Apr 16 13:28:33 PDT 2014
In a library I was writing I was in need of the following:
Write code that takes a function pointer/delegate and an array of
strings that calls the function by parsing each string into the
given functions arguments. And if the function has a return
value, the code will also return the functions return value after
the call.
I had written this functionality before in .NET (C# specifically)
using .NET's runtime reflection. The code looks nice but runtime
reflection has poor performance. Using D's compile-time features
I was able to write a D template function that implemented this
in about 10 lines of code.
ReturnType!Function call(Function)(Function func, const char[][]
args...) if (isCallable!Function)
{
alias Args = ParameterTypeTuple!Function;
if(args.length != Args.length)
throw new Exception(format("Expected %d arguments but got
%d", Args.length, args.length));
Args argsTuple;
foreach(i,Arg;Args) {
argsTuple[i] = to!Arg(args[i]);
}
return func(argsTuple);
}
Here's a unit test to demonstrate its usage:
unittest
{
void voidFunction()
{
writeln("[Test] Called voidFunction()");
}
void randomFunction(int i, uint u, string s, char c)
{
writefln("[Test] Called randomFunction(%s, %s, \"%s\",
'%s')", i, u, s, c);
}
ulong echoUlong(ulong value)
{
writefln("[Test] Called echoUlong(%s)", value);
return value;
}
(&voidFunction).call();
(&randomFunction).call("-1000", "567", "HelloWorld!", "?");
string passedValue = "123456789";
ulong returnValue = (&echoUlong).call(passedValue);
writefln("[Test] echoUlong(%s) = %s", passedValue, returnValue);
try {
(&randomFunction).call("wrong number of args");
assert(0);
} catch(Exception e) {
writefln("[Test] Caught %s: '%s'", typeid(e), e.msg);
}
writeln("[Test] Success");
}
I think this challenge does a great job in demonstrating D's
compile-time power. I couldn't think of a way to do this in C
without doing some type of code generation. The reason I needed
this functionality was because I was writing a remote procedure
call type of library, where the function's being called were
known at compile time, but the arguments (passed over a socket)
had to be processed at runtime. I was wondering if anyone had
good solutions to this problem in other languages. I was very
pleased with the D solution but I predict that solutions in other
languages are going to be much uglier.
More information about the Digitalmars-d
mailing list