December 13, 2008 Re: A template for method forwarding? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Bill Baxter | > 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 Re: A template for method forwarding? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Christian Kamm | 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 Re: A template for method forwarding? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Christopher Wright | 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; } } }}} | |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply