www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Templates convariance

reply michal.minich gmail.com writes:
Now we have interfaces covariance working in D, but Templates covariance is not
implemented yet. Simply:

while you can write this:
Shape s = new Circle();

This fails to compile:
List!(Shape) sList = new List!(Circle)();

To show usefullness of this functionality, here is an example:

class Shape
{
void render()
{
printf ("Shape\n");
}
}

class Circle : Shape
{
void render()
{
printf ("Circle\n");
}
}


class List (T)
{
T item; // for simplicity, just one item possible in this list 
}

void renderShapes (List!(Shape) shapesList)
{
shapesList.item.render();
}

void main()
{
List!(Shape) shapesList = new List!(Shape) ();
shapesList.item = new Shape();

List!(Circle) circlesList = new List!(Circle) ();
circlesList.item = new Circle();

renderShapes ( shapesList ); // this works
//renderShapes ( circlesList ); // *1 - does not compile
renderShapes ( cast(List!(Shape))circlesList ); // *2 - access violation

}

// *1
//test.d(37): function test.renderShapes (List) does not match argument types
(List)
//test.d(37): cannot implicitly convert expression (circlesList) of type
test.List!(Circle).List to test.List!(Shape).List

// *2 application compiles, but when run, crashes with access violation


I think that implementation of this functionality can be very difficult, but
simply said, templates should be covariant if all its instantiation parameters
are covariant.
Jun 20 2006
parent reply Sean Fritz <Sean_member pathlink.com> writes:
In article <e799ce$2idm$1 digitaldaemon.com>, michal.minich gmail.com says...

A list!(Shape) is not the same a a list!(Square).  It sounds like you want some
sort of wildcard matching or something to enforce type bounding like Java/C#
have, but casts are definitely unsafe.

Example code (I'm going to blotch various syntax, sorry in advance):

void foo(List!(Shape) ls) {
ls.add(new Circle) //passes type check locally?
}

..
List!(Square) ls = new List!(Square);
foo(ls);
//but ls now contains a Circle?  Circles don't go in List!(Square)?
,,.
Jun 20 2006
next sibling parent "Boris Wang" <nano.kago hotmail.com> writes:
"Sean Fritz" <Sean_member pathlink.com>
写入消息新闻:e79r79$f64$1 digitaldaemon.com...
 In article <e799ce$2idm$1 digitaldaemon.com>, michal.minich gmail.com 
 says...

 A list!(Shape) is not the same a a list!(Square).  It sounds like you want 
 some
 sort of wildcard matching or something to enforce type bounding like 
 Java/C#
 have, but casts are definitely unsafe.

agreed. 'cast' and 'static if' should not be a solution for this problem, if we want a good programming language.
 Example code (I'm going to blotch various syntax, sorry in advance):

 void foo(List!(Shape) ls) {
 ls.add(new Circle) //passes type check locally?
 }

 ..
 List!(Square) ls = new List!(Square);
 foo(ls);
 //but ls now contains a Circle?  Circles don't go in List!(Square)?
 ,,.


 

Jun 20 2006
prev sibling parent reply Bruno Medeiros <brunodomedeirosATgmail SPAM.com> writes:
Sean Fritz wrote:
 In article <e799ce$2idm$1 digitaldaemon.com>, michal.minich gmail.com says...
 
 A list!(Shape) is not the same a a list!(Square).  It sounds like you want some
 sort of wildcard matching or something to enforce type bounding like Java/C#
 have, but casts are definitely unsafe.
 
 Example code (I'm going to blotch various syntax, sorry in advance):
 
 void foo(List!(Shape) ls) {
 ls.add(new Circle) //passes type check locally?
 }
 
 ...
 List!(Square) ls = new List!(Square);
 foo(ls);
 //but ls now contains a Circle?  Circles don't go in List!(Square)?
 ,,.
 
 

Indeed. I was about to mention that too, because this is a more general problem concerning parameterized collections (Lists, arrays, etc.) in that a parameterized collection type is only covariant with another parameterized collection type if the parameter is invariant. (because the parameter is both an input and an ouput) So for example an array of Numbers can not be (safely) typed as an array of Integers, nor it cannot be typed as an array of Objects. Still, an array of Numbers can be seen as a readonly array of Objects, and as a writeonly array of Integers. -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Jun 21 2006
parent reply michal.minich gmail.com writes:
Maybe this is the way how to solve this
http://lambda-the-ultimate.org/node/1573

..and a publication linked from this blog entry
http://research.microsoft.com/research/pubs/view.aspx?type=inproceedings&id=1215



In article <e7b3q2$22m5$1 digitaldaemon.com>, Bruno Medeiros says...
Sean Fritz wrote:
 In article <e799ce$2idm$1 digitaldaemon.com>, michal.minich gmail.com says...
 
 A list!(Shape) is not the same a a list!(Square).  It sounds like you want some
 sort of wildcard matching or something to enforce type bounding like Java/C#
 have, but casts are definitely unsafe.
 
 Example code (I'm going to blotch various syntax, sorry in advance):
 
 void foo(List!(Shape) ls) {
 ls.add(new Circle) //passes type check locally?
 }
 
 ...
 List!(Square) ls = new List!(Square);
 foo(ls);
 //but ls now contains a Circle?  Circles don't go in List!(Square)?
 ,,.
 
 

Indeed. I was about to mention that too, because this is a more general problem concerning parameterized collections (Lists, arrays, etc.) in that a parameterized collection type is only covariant with another parameterized collection type if the parameter is invariant. (because the parameter is both an input and an ouput) So for example an array of Numbers can not be (safely) typed as an array of Integers, nor it cannot be typed as an array of Objects. Still, an array of Numbers can be seen as a readonly array of Objects, and as a writeonly array of Integers. -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D

Jun 21 2006
parent Bruno Medeiros <brunodomedeirosATgmail SPAM.com> writes:
michal.minich gmail.com wrote:
 Maybe this is the way how to solve this
 http://lambda-the-ultimate.org/node/1573
 
 ...and a publication linked from this blog entry
 http://research.microsoft.com/research/pubs/view.aspx?type=inproceedings&id=1215
 
 

Interesting article (I read chapters 1&2&5) (chapter 3 scared me away :P ). Well, that's one way to solve it, but there are other ways surely, and we don't know which one is better. (for starters: D's template mechanism is very different than C# and Java.) This is a very complex and advanced issue, but not as critical as many other D issues which are likely to get more attention first (and justifiedly so). That said, I want to check out the Java generics semantics, I still haven't look much into Java 1.5 .
 
 In article <e7b3q2$22m5$1 digitaldaemon.com>, Bruno Medeiros says...
 Sean Fritz wrote:
 In article <e799ce$2idm$1 digitaldaemon.com>, michal.minich gmail.com says...

 A list!(Shape) is not the same a a list!(Square).  It sounds like you want some
 sort of wildcard matching or something to enforce type bounding like Java/C#
 have, but casts are definitely unsafe.

 Example code (I'm going to blotch various syntax, sorry in advance):

 void foo(List!(Shape) ls) {
 ls.add(new Circle) //passes type check locally?
 }

 ...
 List!(Square) ls = new List!(Square);
 foo(ls);
 //but ls now contains a Circle?  Circles don't go in List!(Square)?
 ,,.

problem concerning parameterized collections (Lists, arrays, etc.) in that a parameterized collection type is only covariant with another parameterized collection type if the parameter is invariant. (because the parameter is both an input and an ouput) So for example an array of Numbers can not be (safely) typed as an array of Integers, nor it cannot be typed as an array of Objects. Still, an array of Numbers can be seen as a readonly array of Objects, and as a writeonly array of Integers. -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D


Oops, a mistake above, this problem concerns any parameterized (templated) type, not just parameterized collections. -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Jul 02 2006