digitalmars.D.learn - Unusual template specialisation behavior
- Matthias Walter (46/46) Feb 08 2008 Hello guys,
- Christopher Wright (7/19) Feb 08 2008 The compiler should have caught this, I think. You have R and E, but
- Sergey Gromov (23/44) Feb 08 2008 struct ResolveReference (T : Expression !(R, E), R, E)
- Matthias Walter (4/54) Feb 08 2008 Thank you both! I guess, this works, because when passing an Expression ...
- Matthias Walter (9/30) Feb 08 2008 Thanks for that hint. How would such a static if look like?
- Christopher Wright (10/34) Feb 08 2008 template ResolveReference (T) {
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
Feb 08 2008
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.
Feb 08 2008
Christopher Wright <dhasenan gmail.com> wrote:Matthias Walter wrote: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 -- SnakEHello 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.
Feb 08 2008
Sergey Gromov Wrote:Christopher Wright <dhasenan gmail.com> wrote: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 WalterMatthias Walter wrote: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 -- SnakEHello 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.
Feb 08 2008
Christopher Wright Wrote:Matthias Walter wrote: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 WalterHello 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.
Feb 08 2008
Matthias Walter wrote:Christopher Wright Wrote: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.Matthias Walter wrote:Thanks for that hint. How would such a static if look like?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.
Feb 08 2008









Matthias Walter <walter mail.math.uni-magdeburg.de> 