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