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