Function pointer argument to function template

Tom S h3r3tic at remove.mat.uni.torun.pl
Wed May 31 08:08:40 PDT 2006


Daniel Keep wrote:
> Actually, it's quite simple, if utterly evil.  It involves abusing IFTI
> in the most gruesome manner imaginable...
> 
> Detecting the number of arguments looks like this:
> 
> ( ... )
> 

Neat !! I didn't realize IFTI could do that :D


> What do you think of that sneaky use of typedefs?  ^_^  Deducing the
> return type, and argument types is pretty similar (except instead of
> using ArglenN, you use Tr for the return type or Ta, Tb, Tc, etc for the
> argument types).

That's not necessary :>

> The neat upshot of this is that despite using IFTI, I don't actually
> think those functions ever get instantiated; they certainly never run,
> which is kinda cool.

AFAICS, they are instantiated, but never called so the linker or even 
the compiler might optimize them away :)


> Thankfully, I have a nifty little Python script that saves me having to
> actually *type* all that out.  I give it a maximum number of arguments,
> and it goes off and generates the template for me.  Evil was never so easy!

Hehehe, I use it as well for other sorts of stuff, where I have to 
generate lots of such code that would be handled by variadic templates 
if we had them ;)


How about taking it a step further and doing something like:

----
import std.stdio;

struct FuncMeta(int NumArgs, Ret, T0=void, T1=void /+, and, so, on+/) {
	alias FuncMeta Meta;

	static const int	numArgs = NumArgs;
	alias	Ret			RetType;
	alias	T0			Arg0Type;    // these might use static if as well
	alias	T1			Arg1Type;
	/+
	... and so on
	+/
}


template funcInfo(Ret) {
	FuncMeta!(0, Ret) funcInfo(Ret function() x) { assert(false); };
}


template funcInfo(Ret, T0) {
	FuncMeta!(1, Ret, T0) funcInfo(Ret function(T0) x) { assert(false); };
}


template funcInfo(Ret, T0, T1) {
	FuncMeta!(2, Ret, T0, T1) funcInfo(Ret function(T0, T1) x) { 
assert(false); };
}

/+
...

template funcInfo(Ret, T0, T1, ..., Tn) {
	...
}
+/


struct Foo {}
void fooFunc(Foo a, float b) {}
int barFunc(cfloat x) {}


void main(char[][] args) {
	writefln("Number of args of main: ", funcInfo(&main).numArgs);

	writefln("\nfunc foo:");
	alias typeof(funcInfo(&fooFunc)) FooMeta;
	writefln(FooMeta.numArgs);
	writefln(typeid(FooMeta.RetType));
	writefln(typeid(FooMeta.Arg0Type));
	writefln(typeid(FooMeta.Arg1Type));

	writefln("\nfunc bar:");
	alias typeof(funcInfo(&barFunc)) BarMeta;
	writefln(BarMeta.numArgs);
	writefln(typeid(BarMeta.RetType));
	writefln(typeid(BarMeta.Arg0Type));

	static if (BarMeta.numArgs >= 2) {
		writefln(typeid(BarMeta.Arg1Type));
	} else {
		writefln("bar doesn't have Arg1Type");
	}
}


Note that the ArgXType could be static if'fed away so one would get an 
error when trying to access them instead of having them alias to void.


-- 
Tomasz Stachowiak  /+ a.k.a. h3r3tic +/



More information about the Digitalmars-d mailing list