digitalmars.D - Templates convariance
- michal.minich gmail.com (48/48) Jun 20 2006 Now we have interfaces covariance working in D, but Templates covariance...
- Tom S (18/18) Jun 20 2006 Frankly, I wouldn't like to see that 'template covariance' in D. It
- Tom S (5/8) Jun 20 2006 Btw, this test would have to be more complex in case of primitive types,...
- michal.minich gmail.com (3/21) Jun 20 2006 Thank you for casting solution. It should works perfect for my problem. ...
- Tom S (11/13) Jun 20 2006 Basically, the fact that Foo is castable to Bar doesn't mean that
- pragma (16/25) Jun 20 2006 Usually when I come across the need for something like that, I typically...
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
Frankly, I wouldn't like to see that 'template covariance' in D. It would mess things up... How about doing something like: class List(T) { template asList(T1) { .List!(T1) asList() { static if (is(T : T1)) { return cast(.List!(T1))cast(void*)this; } else { return null; // or static assert (false) } } } } then you might write: auto circleList = new List!(Circle); auto shapeList = circleList.asList!(Shape); -- Tomasz Stachowiak /+ a.k.a. h3r3tic +/
Jun 20 2006
Tom S wrote:static if (is(T : T1)) { return cast(.List!(T1))cast(void*)this; } else {Btw, this test would have to be more complex in case of primitive types, but then the 'covariance' couldn't quite work either. -- Tomasz Stachowiak /+ a.k.a. h3r3tic +/
Jun 20 2006
Thank you for casting solution. It should works perfect for my problem. But could you explain me how this can mess things up? In article <e79amd$2kil$1 digitaldaemon.com>, Tom S says...Frankly, I wouldn't like to see that 'template covariance' in D. It would mess things up... How about doing something like: class List(T) { template asList(T1) { .List!(T1) asList() { static if (is(T : T1)) { return cast(.List!(T1))cast(void*)this; } else { return null; // or static assert (false) } } } } then you might write: auto circleList = new List!(Circle); auto shapeList = circleList.asList!(Shape); -- Tomasz Stachowiak /+ a.k.a. h3r3tic +/
Jun 20 2006
michal.minich gmail.com wrote:Thank you for casting solution. It should works perfect for my problem. But could you explain me how this can mess things up?Basically, the fact that Foo is castable to Bar doesn't mean that Baz!(Foo) should be castable to Baz!(Bar). Their implementation may be totally different based on some static if's and other fancy stuff. IMO they are two totally separate classes. If that kind of invariance would be to be allowed, then one would sometimes need to specify explicitly that a given Baz!(Bar) should not be casted to a Baz!(Foo). And in that case, why not reverse the idea and just use the method I provided in the remaining cases ? :) -- Tomasz Stachowiak /+ a.k.a. h3r3tic +/
Jun 20 2006
In article <e799dr$2igf$1 digitaldaemon.com>, michal.minich gmail.com says...[snip] class List (T) { T item; // for simplicity, just one item possible in this list } void renderShapes (List!(Shape) shapesList) { shapesList.item.render(); }Usually when I come across the need for something like that, I typically throw in a common base class or interface for my template instances, so they are castable from one to the other. interface IShapeList{ void renderShapes(IShapeList list); } class ShapeList(T): IShapeList{ /*...*/ } As a side-effect, the above is now very friendly to use with non-template based IShapeLists. ;) I'm not a metaprogramming expert by any means, but I don't think covariance with templates can be solved using a rule general enough to be implemented (easily) in the compiler itself. The problem is that templates allow one to create interfaces derived from supplied types that can be composed in so many arbitrary ways. - EricAnderton at yahoo
Jun 20 2006