May 31, 2006
Tom S skrev:
> 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

I agree! But how can you call something this beautiful evil? :)

>> 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 ;)

I think you can manage this without needing to resort to autogenerated code by using a generic variadic template list generator. There will still be a hard-coded limit in the maximum number of function arguments though.

> 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
>     +/
> }

[snip the rest]

Marvelous! this will be very useful for me in a number of places.

/Oskar
June 03, 2006
Tom S wrote:
> Hey there :)
> 
> I came up with this:
> 
> ----
> 
> import std.stdio;
> 
> template Deref(T) {
>         alias typeof(*T) Deref;
> }
> 
> template RetType(T) {
>         static if (is(Deref!(T) U == function)) {
>                 alias U RetType;
>         } else static assert (false);
> }
> 
> template Bar(T, U=RetType!(T)) {
>         U Bar(T t) {
>                 writefln(typeid(U));
> 
>                 // do something :P
>                 return U.init;
>         }
> }
> 
> 
> cfloat func(int a, float b) {
>         return 1.f + 0i;
> }
> 
> 
> void main() {
>         writefln(Bar(&func));
> }
> 
> 
> -- 
> Tomasz Stachowiak  /+ a.k.a. h3r3tic +/

Just for the record, here's an alternative version, smaller, but less flexible(because you must know the parameters of the T function, and you have worse error messages):


template Bar(T, U = typeof(T(0,0)) ) {
  U Bar(T t) {
    writefln(typeid(U));

    return U.init;
  }
}

cfloat func(int a, float b) {
  return 1.f + 0i;
}


void main() {
  writefln(Bar(&func));
}


-- 
Bruno Medeiros - CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
June 03, 2006
Tom S wrote:
> 
> 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.
> 
> 

Hum, pretty nice!

-- 
Bruno Medeiros - CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
1 2
Next ›   Last »