|
Archives
D Programming
digitalmars.D
digitalmars.D.bugs
digitalmars.D.dtl
digitalmars.D.ide
digitalmars.D.dwt
digitalmars.D.announce
digitalmars.D.learn
digitalmars.D.debugger
D.gnu
D
C/C++ Programming
c++
c++.announce
c++.atl
c++.beta
c++.chat
c++.command-line
c++.dos
c++.dos.16-bits
c++.dos.32-bits
c++.idde
c++.mfc
c++.rtl
c++.stl
c++.stl.hp
c++.stl.port
c++.stl.sgi
c++.stlsoft
c++.windows
c++.windows.16-bits
c++.windows.32-bits
c++.wxwindows
digitalmars.empire
digitalmars.DMDScript
electronics
|
digitalmars.D.learn - 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
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.
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
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
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
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))
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.
|
|