Hi all, it's been a while since this question, and I don't know how to solve it either. The following code passes all the test using the last version of dmd (2.059).
import std.container, std.algorithm; //non const case void assertequal(T)(SList!(T) l, int[] r) { assert(equal(l[], r)); } //const case void const_assertequal(T)(const SList!(T) l, int[] r) { assert(equal(l[], r)); } unittest{ SList!(int) l; l.insertFront(2); l.insertFront(1); assertequal (l, [1,2]); assert(!__traits(compiles, const_assertequal(l, [1,2]))); } The conflict with the last assertion is that opSplice can't be applied to const. So, I looked at the container module, and made a minimal example of a list myself (emulating SList). struct List { struct Node { Node* next; int val; } private Node* first; struct Range { //sorry about "actual", it should have been current private Node* actual; this(Node* first) {actual = first;} @property front() {return actual.val;} @property empty() const {return !actual;} void popFront() {assert(!empty); actual = actual.next;} Range save() {return this;} } unittest{static assert(isForwardRange!(Range));} void add(int v) { Node * next = first; first = new Node; first.val = v; first.next = next; } Range opSlice() { return Range(first); } } void assertequal(L : List)(L l, int[] r) { assert(equal(l[], r)); } void assertequal_const(L : List)(L l, int[] r) { assert(equal(l[], r)); } unittest{ List l; l.add(2); l.add(1); assert(equal(l[], [1,2])); assertequal (l, [1,2]); assert(!__traits(compiles, const_assertequal(l, [1,2]))); } As far as I know, the problem comes with the transitivity of const. In assertequal_const, l.first has type const(Node*), thus it can't be converted to Node* in Range's constructor. I can't manage to find a workaround here, because l.first will always have type const(Node*), but for traversing the list I require to copy l.first into some node, say actual, whose type is Node* so that I can move it doing actual = actual.next. I would be happy to do actual = cast(Node*)(l.first) actual = actual.next; but that code is suppose to be undefined, isn't it? (http://dlang.org/const3.html : Removing Immutable With A Cast). So, my question is how can I (correctly) traverse a const SList, const DList, etc? Best, Francisco. PS: sorry for the long mail.