How to change DList elements by means of foreach?

monarch_dodra monarchdodra at gmail.com
Mon Sep 10 04:37:15 PDT 2012


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.




More information about the Digitalmars-d-learn mailing list