how is this array subtyping inside struct (bug?) possible?
Paul Backus
snarwin at gmail.com
Sun Aug 9 20:30:35 UTC 2020
On Sunday, 9 August 2020 at 18:45:07 UTC, mw wrote:
> Hi,
>
> I want to share an array among a number of structs, with
> subtyping, I tried this, and find some strange behavior:
>
> ```
> class SharedArray(T) {
> public T[] array;
> alias array this; // subtyping
> }
>
> alias Filenames = SharedArray!(string);
>
> struct S {
> Filenames fns;
> void alloc() {
> fns = new Filenames();
> }
> }
>
> void main(string[] args) {
> S s0;
> s0.alloc();
> s0.fns ~= "abc";
>
> foreach (i; 0..3) {
> S* s1 = new S();
> *s1 = s0; // copy the value from s0 to *s1
> writeln(s0.fns);
> }
> }
> ```
>
> program output:
> ```
> ["abc"]
> []
> []
> ```
>
> why s0.fns changed after copy the value from s0 to *s1?
>
> Is this a bug?
No, it's not a bug, it's just a weird quirk of how `alias this`
interacts with reference types like classes.
When you pass a range to `writeln`, it will iterate the range
using `front` and `popFront` in order to print each of the
elements. Doing this consumes the range.
Normally, that's not a problem, because writeln takes its
arguments by value, so any range you pass to it will be copied,
and only the copy will be consumed. However, because you've made
your `Filenames` class into an input range using `alias this`,
and classes are reference types, consuming a copy of the range
also consumes the original.
The solution is to use the `save` function from `std.range` to
create an independent copy of the range for `writeln` to iterate:
import std.range;
writeln(s0.fns.save);
More information about the Digitalmars-d
mailing list