www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 2126] New: class template specialization and inheritance

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2126

           Summary: class template specialization and inheritance
           Product: D
           Version: unspecified
          Platform: PC
        OS/Version: Linux
            Status: NEW
          Severity: normal
          Priority: P2
         Component: www.digitalmars.com
        AssignedTo: bugzilla digitalmars.com
        ReportedBy: michael.kiermaier gmx.net


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


-- 
May 24 2008
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2126





------- Comment #1 from brunodomedeiros+bugz gmail.com  2008-06-13 16:27 -------
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
}


-- 
Jun 13 2008
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2126


Don <clugdbug yahoo.com.au> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |spec
                 CC|                            |clugdbug yahoo.com.au
          Component|www.digitalmars.com         |DMD
            Version|unspecified                 |D1 & D2
           Severity|normal                      |enhancement


-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jun 14 2010