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?

Reply via email to