Jonathan: > It's just easier to cope with containers not being assignable to one another > just because the type of the elements of one is derived from the type of the > elements of the other.
Scala does this with + or - annotation on types: List[+T] : List is parameterized by type T, and is covariant in T. A contravariant version would use [-T] See http://www.scala-lang.org/node/129 In D, a List(T) struct could have an opAssign doing the conversion: struct List(T) { ... void opAssign(U : T)(List!U rhs) { ... walk the list, transform the U's into T's } } You can then test any container to see if it's covariant or contravariant: see if the type defines the correct opAssign. Or maybe an opCast(LU)() if (is(LU lu == List!U, U) && is(U : T)) ^^^^^^^^^^ I'm not sure we can do that in template constraints. We may have to express it with an external template: if( isA!(List, LU) && is(ExtractType!LU : T)) Philippe