Pass function (not alias) to template and/or delegate-ize a template argument

cc cc at nevernet.com
Mon Jun 11 06:46:02 UTC 2018


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?


More information about the Digitalmars-d-learn mailing list