how is this array subtyping inside struct (bug?) possible?

mw mingwu at gmail.com
Mon Aug 10 19:39:28 UTC 2020


On Monday, 10 August 2020 at 19:30:18 UTC, Steven Schveighoffer 
wrote:
> On 8/10/20 2:36 PM, mw wrote:
>> On Monday, 10 August 2020 at 18:29:56 UTC, mw wrote:
>>> and where in this doc on range:
>>>
>>> https://tour.dlang.org/tour/en/basics/ranges
>>>
>>> it is mentioned that: the length property of the range will 
>>> be changed after the range is "consumed" by foreach loop?
>>>
>>> ```
>>> foreach (element; range)
>>> {
>>>     // Loop body...
>>> }
>>> it's internally rewritten similar to the following:
>>>
>>> for (auto __rangeCopy = range;
>>>      !__rangeCopy.empty;
>>>      __rangeCopy.popFront())
>>>  {
>>>     auto element = __rangeCopy.front;
>>>     // Loop body...
>>> }
>>> ```
>> 
>> And wait, ... did I saw "__rangeCopy" here?  it should be a 
>> *copy*?!
>> 
>> 
>
> In your code, the type of "range" is SharedArray!(string) which 
> is a class or *reference type*.
>
> So let's follow along what happens:
>
> SharedArray!(string) fns;
> for(auto __rangeCopy = fns;
>
> // the above makes a copy of a *class reference*, which means 
> it does not make a copy of the *array data* or even the array 
> reference. It's like copying a pointer to the array.
>
>     !__rangeCopy.empty;
>
> // SharedArray(T) does not have empty member, so this forwards 
> to the array, it's like saying:
> // !__rangeCopy.array.empty
>
>     __rangeCopy.popFront())
>
> // This is equivalent to __rangeCopy.array.popFront, which 
> alters the array inside the ONE SHARED class instance.


This still doesn't explain why the underlying array.length is 
modified after the range to consumed; too much black magic is 
happening here.

> How to fix? extract the array before iterating:
>
> writeln(s0.fns.array);

This defeats the purpose, i.e. the convenience that subtyping 
mechanism supposed to provide.




More information about the Digitalmars-d mailing list