Bug 408 – Template instance matching doesn't work sometimes
Status
RESOLVED
Resolution
INVALID
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D1 (retired)
Platform
x86
OS
Windows
Creation time
2006-10-08T13:39:00Z
Last change time
2014-02-15T13:19:39Z
Keywords
rejects-valid
Assigned to
bugzilla
Creator
burton-radons
Comments
Comment #0 by burton-radons — 2006-10-08T13:39:39Z
Code fails compilation with:
argh.d(5): function math.matrix.f!(2u).f (S ) does not match argument types (S )
argh.d(5): cannot implicitly convert expression (*this) of type S to S
As far as I can tell it is valid code.
==
struct S (uint C)
{
void argh ()
{
f! (C) (*this);
}
}
template f (uint C)
{
void f (S! (C) a)
{
}
}
alias S! (2) s;
Comment #1 by burton-radons — 2006-10-08T14:15:09Z
Found it. If a template instantiation literal value is given the type "uint", D casts it to "int" implicitly so it no longer works against a second instantiation. So this works:
struct O (int T)
{
.O! (T) f () { return *this; }
}
alias O! (2) o;
But this fails:
struct O (uint T)
{
.O! (T) f () { return *this; }
}
alias O! (2) o;
Comment #2 by bugzilla — 2006-10-16T04:20:45Z
This is working as designed (although the error message isn't great). The issue is, is the template instance made from the argument before the cast to the template value type, or after? D's design is to do make it from the original type. In the third example, 2 is an int, but T is a uint, hence the two instances are not the same.
The reason for this is so that template specializations can be added without upsetting the name mangling.
Comment #3 by burton-radons — 2006-10-16T12:13:46Z
It's not complaining about the outside template instantiation, it's complaining about the nested one. In other words, 2 is treated happily as a uint by an explicit instantiation, but is not treated as anything compatible to a uint by a dependent instantiation.
This rule (which doesn't exist in the documentation) isn't even applied consistently! This, which has EXACTLY the same issue as the first example, works quite happily:
struct S (float C)
{
void argh ()
{
f! (C) (*this);
}
}
template f (float C)
{
void f (S! (C) a)
{
}
}
alias S! (2) s;
Try to make a design of this and you'll come out with spagghetti, there's no rhyme or reason to it.