On Monday, 10 September 2012 at 11:18:29 UTC, Alexandr Druzhinin wrote:
I have code:

import std.container;

int main() {
// array
int[] array = [0];
foreach(ref value; array) {
        value += 50;
        assert(value == 50);
}

foreach(value; array) {
        assert(value == 50);
}       

// double-linked list;
DList!int dlist;
dlist.insertFront(0);
foreach(ref value; dlist) {
        value += 50;
        assert(value == 50);
}

foreach(value; dlist) {
        assert(value == 50);  // Why do I have assertion failure here?
}

}
How to change the value of elements of DList?

There is a know bug: foreach with ref does not currently work these containers. The reason is that the container's front does not actually expose a reference, but a value, and that is what is being changed (the returned value).

There is no hope in sight to really *ever* make it work, because "container.front += 5" can't be made to work if the returned value is not a reference: Unlike indexes that define opIndexOpAssign, there is no opFrontOpAssign.

What bothers *me* though is that the code compiles fine, biting more than 1 user in the process.

Anyways... the workaround is* making an explicit loop, with temporary object that is fed back into front, like this:

import std.container;

--------
void main()
{
    // double-linked list;
    DList!int dlist;
    dlist.insertFront(0);
    auto slice = dlist[]; //Extract a range manually
    for( ; !slice.empty ; slice.popFront() )
    {
      auto value = slice.front; //Extract the value
      value += 50;              //Increment the value
      slice.front() = value;    //Feed back into the range*
    }

    foreach(value; dlist) {
      assert(value == 50);  //Now this works fine
    }
}
--------

Well... this *would* work, but apparently, the implementation of DList.Range doesn't define front(T value). This makes the Range pretty much read-only. My guess is that this was an omission on the part of the implementer. I will fix it so that it works.


Reply via email to