Bug 2126 – class template specialization and inheritance
Status
RESOLVED
Resolution
WORKSFORME
Severity
enhancement
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
x86
OS
Linux
Creation time
2008-05-24T05:51:08Z
Last change time
2018-05-15T13:59:57Z
Keywords
spec
Assigned to
No Owner
Creator
Michael Kiermaier
Comments
Comment #0 by michael.kiermaier — 2008-05-24T05:51:08Z
The following code
//begin code
import std.stdio;
class A(TT) { }
class B(TT) : A!(TT) { }
class C(T) {
static void tellMe() {
writefln("implementation for generic T.");
}
}
class C(T:A!(TT),TT) {
static void tellMe() {
writefln("implememtation for T the same as or derived from A!(TT).");
}
}
void main() {
C!(A!(int)).tellMe();
C!(B!(int)).tellMe();
C!(int).tellMe();
}
//end code
compiled by DMD v2.008 produces the output
implememtation for T the same as or derived from A!(TT).
implementation for generic T.
implementation for generic T.
According to the documentation, the colon in 'C(T:A!(TT),TT)' means "the same as or derived from". So the second line of the output should be "implememtation for T the same as or derived from A!(TT)." in my opinion.
There was a discussion about this issue in digitalmars.D, see
http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=71757
~Michael
Comment #1 by bruno.do.medeiros+deebugz — 2008-06-13T16:27:36Z
I think this behavior is not a bug, it could be a request for enhancement at most. I'm not sure it's worth it though, since it could be somewhat complicated, and a trivial workaround is available.
First of all, if I got it right, here's why it doesn't work: The thing is, the "TT : A!(TT)" is a partial specialization, and because of that, it behaves differently from a normal specialization, such as ": A" where A where a class or some other type. It has to be able to deduce type TT, and because of that it has to look at the template instance parameter, such as "A!(int)", and see that it is created from template A with parameters (int), and see that it matches "A!(TT)", with TT being int. That is somewhat odd in itself, since almost everywhere in D a template instance is kinda "opaque": the program sees the code that was generated from the template, but you can't see the template or arguments that comprise the instanciation. (so in that sense I'm surprised that the "C!(A!(int))" case even works at all)
But the problem is, when you try to match "B!(int)" with "A!(TT)", the compiler does not match them, because B is not A. They are different templates. Of course, we can see that B!(int) derives from A!(int), so in fact "B!(int)" should match ": A!(TT)". However, that vision is lost to the compiler. It doesn't attempt to re-match using the supertypes of B!(int).
The semantics of D could be changed to account for this, but again, I'm not sure it's worth it. I find template specialization rules to already be somewhat complicated and hard to understand, and I would prefer things to not become unnecessarily complicated.
Also, there is a trivial workaround, use marker interfaces, to control the specialization, thus using only normal specialization rules:
--- ---
import std.stdio;
interface RawA {}
interface RawB {}
class A(T) : RawA { }
class B(T) : A!(T), RawB { }
class B2 : A!(short) { }
class C(T) {
pragma(msg, "implementation for generic T.");
static void tellMe() {
writefln("implementation for generic T.");
}
}
class C(T: RawA) {
pragma(msg, "implementation for T: " ~ (typeof(T)).stringof);
static void tellMe() {
writefln("implementation for T the same as or derived from A!(ANY).");
}
}
void main() {
C!(A!(int)).tellMe(); // implementation for T: A
C!(B!(int)).tellMe(); // implementation for T: B
C!(int).tellMe(); // implementation for generic T.
C!(B2).tellMe(); // implementation for T: B2
}
Comment #2 by dmitry.olsh — 2018-05-15T13:59:57Z
> According to the documentation, the colon in 'C(T:A!(TT),TT)' means "the same > as or derived from". So the second line of the output should be
> "implememtation for T the same as or derived from A!(TT)." in my opinion.
Was fixed in the meantime, since the original code in 2.079 prints:
implememtation for T the same as or derived from A!(TT).
implememtation for T the same as or derived from A!(TT).
implementation for generic T.
Whereas it was:
implememtation for T the same as or derived from A!(TT).
implementation for generic T.
implementation for generic T.
So this ehancement was done sometime ago.