December 13, 2008
> So looks like bad stringof is the culprit, once again.

Why use stringof when you have an alias? This works for me in D1 - if you discount default arguments and parameter storage classes (will templates ever be able to touch these?).

template Forward(string clName, Methods...) {
    static if(Methods.length == 1) {
        mixin ForwardImpl!(clName, Methods[0]);
    } else {
        mixin ForwardImpl!(clName, Methods[0]);
        mixin Forward!(clName, Methods[1..$]);
    }
}

template ForwardImpl(string clName, string method) {
    private mixin("alias ParameterTypeTuple!(" ~ clName ~ "."
                  ~ method ~ ") params;");
    private mixin("alias ReturnType!(" ~ clName ~ "."
                  ~ method ~ ") retType;");

    mixin("retType " ~ method ~
        "(params args){ return " ~ clName ~ "."
        ~ method ~ "(args); }");
}

December 13, 2008
Christian Kamm wrote:
>> So looks like bad stringof is the culprit, once again.
> 
> Why use stringof when you have an alias? This works for me in D1 - if you
> discount default arguments and parameter storage classes (will templates
> ever be able to touch these?).

stringof sucks, but it's easy to work with.

Your solution doesn't deal with method overloads. Passing in a method alias would work:

template Forward(string classname, alias method)
{
   mixin ("ReturnTypeOf!(method) " ~ method.stringof ~ "(ParameterTupleOf!(Method) parameters) {
	return composed." ~ method.stringof ~ "(parameters);
	}");
}

Except method.stringof doesn't work, so you have to do it like this:
template strof(alias method)
{
    const strof = (&method).stringof[2..$];
}

template Forward(char[] classname, alias method)
{
   mixin ("ReturnTypeOf!(method) " ~ strof!(method) ~ "(ParameterTupleOf!(method) parameters) {
        return composed." ~ strof!(method) ~ "(parameters); }");
}
December 13, 2008
On 2008-12-13 15:29:19 +0100, Christopher Wright <dhasenan@gmail.com> said:

> Christian Kamm wrote:
>>> So looks like bad stringof is the culprit, once again.
>> 
>> Why use stringof when you have an alias? This works for me in D1 - if you
>> discount default arguments and parameter storage classes (will templates
>> ever be able to touch these?).
> 
> stringof sucks, but it's easy to work with.
> 
> Your solution doesn't deal with method overloads. Passing in a method alias would work:
> 
> template Forward(string classname, alias method)
> {
>     mixin ("ReturnTypeOf!(method) " ~ method.stringof ~ "(ParameterTupleOf!(Method) parameters) {
> 	return composed." ~ method.stringof ~ "(parameters);
> 	}");
> }
> 
> Except method.stringof doesn't work, so you have to do it like this:
> template strof(alias method)
> {
>      const strof = (&method).stringof[2..$];
> }
> 
> template Forward(char[] classname, alias method)
> {
>     mixin ("ReturnTypeOf!(method) " ~ strof!(method) ~ "(ParameterTupleOf!(method) parameters) {
>          return composed." ~ strof!(method) ~ "(parameters); }");
> }

In my testing framework I had first a version using stringof, and I was able to pass the type or alias directly, this solved many issues.
I think that if doable passing types and aliases is indeed better than strings.

somewhat related to this topic I just found out that is(... return/function/delegate) behave in a way that I did not expect, given a method that returns an int and one that has an int argument (get/set) one has:

typeof(&A.ret_int):int function()
typeof(&A.ret_int) U==return:int
typeof(&A.init.ret_int):int delegate()
typeof(&A.init.ret_int) T==return:int
typeof(&A.init.ret_int) T==delegate:int
typeof(&A.ret_void):void function(int a)
typeof(&A.ret_void) U==return:int
typeof(&A.init.ret_void):void delegate(int a)
typeof(&A.init.ret_void) T==return:int
typeof(&A.init.ret_void) T==delegate:int

for me it is ok as I wanted to have the type of the property getter/setter, but it is not what I would have expected from the documentation...
The prviosu running this program

{{{
import tango.io.Stdout;

class A{
 int ret_int(){ return 3; }
 void ret_void(int a){ }
}

void main(){
  Stdout("typeof(&A.ret_int):")(typeof(&A.ret_int).stringof).newline;
  static if(is(typeof(&A.ret_int) U==function))
       Stdout("typeof(&A.ret_int) U==function:")(U.stringof).newline;
  static if(is(typeof(&A.ret_int) U==return))
       Stdout("typeof(&A.ret_int) U==return:")(U.stringof).newline;
  Stdout("typeof(&A.init.ret_int):")(typeof(&A.init.ret_int).stringof).newline;


 static if(is(typeof(&A.init.ret_int) T==return)){
       Stdout("typeof(&A.init.ret_int) T==return:")(T.stringof).newline;
  }
  static if(is(typeof(&A.init.ret_int) T==function)){
       Stdout("typeof(&A.init.ret_int) T==function:")(T.stringof).newline;
  }
  static if(is(typeof(&A.init.ret_int) T==delegate)){
      Stdout("typeof(&A.init.ret_int) T==delegate:")(T.stringof).newline;
      static if(is(T U==function))
           Stdout("&A.init.ret_int delegate function:")(U.stringof).newline;
      static if(is(T U==return))
           Stdout("&A.init.ret_int delegate return:")(U.stringof).newline;
  }
  Stdout("typeof(&A.ret_void):")(typeof(&A.ret_void).stringof).newline;
  static if(is(typeof(&A.ret_void) U==function))
       Stdout("typeof(&A.ret_void) U==function:")(U.stringof).newline;
  static if(is(typeof(&A.ret_void) U==return))
       Stdout("typeof(&A.ret_void) U==return:")(U.stringof).newline;
  Stdout("typeof(&A.init.ret_void):")(typeof(&A.init.ret_void).stringof).newline;


 static if(is(typeof(&A.init.ret_void) T==return)){
       Stdout("typeof(&A.init.ret_void) T==return:")(T.stringof).newline;
  }
  static if(is(typeof(&A.init.ret_void) T==delegate)){
      Stdout("typeof(&A.init.ret_void) T==delegate:")(T.stringof).newline;
      static if(is(T U==function))
           Stdout("typeof(&A.init.ret_void) delegate function:")(U.stringof).newline;
      static if(is(T U==return))
           Stdout("typeof(&A.init.ret_void) delegate return:")(U.stringof).newline;
  }
}
}}}

1 2
Next ›   Last »