| |
 | Posted by Adam D. Ruppe in reply to H. S. Teoh | Permalink Reply |
|
Adam D. Ruppe 
Posted in reply to H. S. Teoh
| On Tuesday, 10 September 2013 at 21:16:56 UTC, H. S. Teoh wrote:
> My first guess would be: _methods["test"]();
Variant doesn't wrap the function and thus won't know how to call it; it doesn't implement opCall, and even if it did, it won't know types the arguments and return value are.
My guess would be to get the static type:
auto dg = v.get!(void delegate());
dg();
........ except this is throwing at runtime:
Variant: attempting to use incompatible types void()* and void()*
Ugh, that's annoying. Maybe using Variant isn't the right way. The technique I use to for storing random methods is to store a wrapper function instead. The wrapper function converts all the arguments into one common type (e.g. Variant) so then your methods array can be one type of delegate instead of a Variant[].
Variant delegate(Variant[] args)[] _methods;
public void addMethod(T)(string name, T func)
{
this._methods ~= delegate Variant(Variant[] args) {
import std.traits;
import std.conv;
ParameterTypeTuple!func argTuple;
foreach(idx, arg; argTuple) {
argTuple = args[idx].get!(typeof(arg));
}
Variant returned;
static if(is(ReturnType!func == void))
func(argTuple);
else
returned = func(argTuple);
return returned;
};
}
Then, when you call it, the static type of the methods wrapper is always the same and you can handle arguments and return value by wrapping/unwrapping the Variants.
You might have to cast away const when assigning to the argTuple or prepopulate it with default arguments, etc. The code here will work in simple cases though to get you started.
|