Is it possible to pass a class member function as a template
argument in such a way that it can 1. be called during runtime,
and 2. still retrieve the UDAs of the function itself? For
example, given this setup:
struct MYUDA {}
class Foo {
@(MYUDA) int bar(int x) { return x*2; }
}
auto foo = new Foo();
Neither of these will work:
void FCALL(alias F, V...)(V args) {
assert(hasUDA!(F, MYUDA)); // Ok
//assert(F(args) == 10); // Compilation Error: need `this` for
`bar` of type `int(int x)`
}
FCALL!(foo.bar)(5);
void DCALL(V...)(int delegate(V) func, V args) {
//assert(hasUDA!(func, MYUDA)); // Assertion failure (runtime
delegate can't see compile-time UDAs)
assert(func(args) == 12); // Ok
}
DCALL(&foo.bar, 6);
However, I can combine them into one function like so:
void TCALL(alias F, V...)(int delegate(V) func, V args) {
assert(hasUDA!(F, MYUDA)); // Ok
assert(func(args) == 14); // Ok
}
TCALL!(foo.bar)(&foo.bar, 7);
But it feels ugly having to write the same thing twice (foo.bar
and &foo.bar). I'd like to simply this somehow. Given a
template declaration like "void CALL(alias F)( ... )" is there
some way to write a function parameter that takes a
delegate-of-F? Such that I can ultimate call the function as
CALL(&foo.bar) and the template parameter alias is inferred.
I did figure out I can do it with mixins like so:
void MCALL(string func, V...)(V args) {
mixin(`assert(hasUDA!(`~func~`, MYUDA));`); // Ok
mixin(`assert(`~func~`(args) == 16);`); // Ok
}
MCALL!"foo.bar"(8);
Which works. Is this the "best" way to do this? Or is there
another pattern that looks cleaner?