Thread overview | ||||||||
---|---|---|---|---|---|---|---|---|
|
February 08, 2008 Unusual template specialisation behavior | ||||
---|---|---|---|---|
| ||||
Hello guys, Here's a (minimal) code snippet for my problem: | struct Expression (R, E) { } | | struct ResolveReference (T) | { | alias T reference_type; | } | | struct ResolveReference (T : Expression !(R, E)) | { | alias T* reference_type; | } | | void printRefType (T) () | { | Stdout (ResolveReference !(Expression !(T, T)).reference_type.stringof).newline; | } | int main (char[][] args) | { | printRefType !(uint); | printRefType !(int); | printRefType !(long); | printRefType !(char); | printRefType !(float); | | return 0; | } The output is: | Expression!(uint,uint) | Expression!(int,int) * | Expression!(long,long) | Expression!(char,char) | Expression!(float,float) If my understanding of template specialisation is correct, only the second call instanciates the template "ResolveReference (T : Expression !(R, E))" and the other ones choose "ResolveReference (T)". Why does this happen only for ints? My intended behavior would be, that ResolveReference.reference_type is T*, if T is an Expression and T if not. Thus, I expected, that this code returns | Expression!(uint,uint) * | Expression!(int,int) * | Expression!(long,long) * | Expression!(char,char) * | Expression!(float,float) * btw, this is tested on Linux, Tango rev 3152, Digital Mars D Compiler v1.021. Hopefully, I did not miss a bug-fix. best regards Matthias Walter |
February 08, 2008 Re: Unusual template specialisation behavior | ||||
---|---|---|---|---|
| ||||
Posted in reply to Matthias Walter | Matthias Walter wrote:
> Hello guys,
>
> Here's a (minimal) code snippet for my problem:
>
> | struct Expression (R, E) { }
> | | struct ResolveReference (T)
> | {
> | alias T reference_type;
> | }
> | | struct ResolveReference (T : Expression !(R, E))
The compiler should have caught this, I think. You have R and E, but they aren't defined. They default to int (which is why you saw that behavior), but not being defined, they should be a compile-time error.
The proper way to do this, unfortunately, involves static if rather than overloading. At least if you want your users to supply a single argument in all cases.
|
February 08, 2008 Re: Unusual template specialisation behavior | ||||
---|---|---|---|---|
| ||||
Posted in reply to Christopher Wright | Christopher Wright <dhasenan@gmail.com> wrote: > Matthias Walter wrote: > > Hello guys, > > > > Here's a (minimal) code snippet for my problem: > > > > | struct Expression (R, E) { } > > | > > | struct ResolveReference (T) > > | { > > | alias T reference_type; > > | } > > | > > | struct ResolveReference (T : Expression !(R, E)) > > The compiler should have caught this, I think. You have R and E, but they aren't defined. They default to int (which is why you saw that behavior), but not being defined, they should be a compile-time error. > > The proper way to do this, unfortunately, involves static if rather than overloading. At least if you want your users to supply a single argument in all cases. struct ResolveReference (T : Expression !(R, E), R, E) { alias T* reference_type; } works just fine: void main (char[][] args) { printRefType !(uint); printRefType !(int); printRefType !(long); printRefType !(char); printRefType !(float); Stdout (ResolveReference !(uint).reference_type.stringof).newline; } Expression!(uint,uint)* Expression!(int,int)* Expression!(long,long)* Expression!(char,char)* Expression!(float,float)* uint -- SnakE |
February 08, 2008 Re: Unusual template specialisation behavior | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sergey Gromov | Sergey Gromov Wrote:
> Christopher Wright <dhasenan@gmail.com> wrote:
> > Matthias Walter wrote:
> > > Hello guys,
> > >
> > > Here's a (minimal) code snippet for my problem:
> > >
> > > | struct Expression (R, E) { }
> > > |
> > > | struct ResolveReference (T)
> > > | {
> > > | alias T reference_type;
> > > | }
> > > |
> > > | struct ResolveReference (T : Expression !(R, E))
> >
> > The compiler should have caught this, I think. You have R and E, but they aren't defined. They default to int (which is why you saw that behavior), but not being defined, they should be a compile-time error.
> >
> > The proper way to do this, unfortunately, involves static if rather than overloading. At least if you want your users to supply a single argument in all cases.
>
> struct ResolveReference (T : Expression !(R, E), R, E)
> {
> alias T* reference_type;
> }
>
> works just fine:
>
> void main (char[][] args)
> {
> printRefType !(uint);
> printRefType !(int);
> printRefType !(long);
> printRefType !(char);
> printRefType !(float);
>
> Stdout (ResolveReference !(uint).reference_type.stringof).newline;
> }
>
> Expression!(uint,uint)*
> Expression!(int,int)*
> Expression!(long,long)*
> Expression!(char,char)*
> Expression!(float,float)*
> uint
>
> --
> SnakE
Thank you both! I guess, this works, because when passing an Expression !(R, E), the 2nd and 3rd specialisation parameters R and E are deduced and everything works fine, right? Thanks for your help!
best regards
Matthias Walter
|
February 08, 2008 Re: Unusual template specialisation behavior | ||||
---|---|---|---|---|
| ||||
Posted in reply to Christopher Wright | Christopher Wright Wrote:
> Matthias Walter wrote:
> > Hello guys,
> >
> > Here's a (minimal) code snippet for my problem:
> >
> > | struct Expression (R, E) { }
> > |
> > | struct ResolveReference (T)
> > | {
> > | alias T reference_type;
> > | }
> > |
> > | struct ResolveReference (T : Expression !(R, E))
>
> The compiler should have caught this, I think. You have R and E, but they aren't defined. They default to int (which is why you saw that behavior), but not being defined, they should be a compile-time error.
>
> The proper way to do this, unfortunately, involves static if rather than overloading. At least if you want your users to supply a single argument in all cases.
Thanks for that hint. How would such a static if look like?
I currently have
| static if (is (T == struct)).
This works for distinguishing native datatypes like int from my Expression-Templates.
But is there a native way to statically check, whether T is some specialisation like
"T == Expression !(R, E)" (for all R, E).
best regards
Matthias Walter
|
February 08, 2008 Re: Unusual template specialisation behavior | ||||
---|---|---|---|---|
| ||||
Posted in reply to Matthias Walter | Matthias Walter wrote:
> Christopher Wright Wrote:
>
>> Matthias Walter wrote:
>>> Hello guys,
>>>
>>> Here's a (minimal) code snippet for my problem:
>>>
>>> | struct Expression (R, E) { }
>>> | | struct ResolveReference (T)
>>> | {
>>> | alias T reference_type;
>>> | }
>>> | | struct ResolveReference (T : Expression !(R, E))
>> The compiler should have caught this, I think. You have R and E, but they aren't defined. They default to int (which is why you saw that behavior), but not being defined, they should be a compile-time error.
>>
>> The proper way to do this, unfortunately, involves static if rather than overloading. At least if you want your users to supply a single argument in all cases.
>
> Thanks for that hint. How would such a static if look like?
template ResolveReference (T) {
static if (is (T == Expression!(R, E))) {
// or `static if (is (T == Expression!(R, E), R, E)) {`
alias T* ResolveReference;
} else {
alias T ResolveReference;
}
}
Except that doesn't work, right now. There's a bug listed for it.
|
Copyright © 1999-2021 by the D Language Foundation