Last night I encountered some strange behavior of the dup function.
import std.stdio;
struct S {
int x;
int y;
int[] arr;
this(ref return scope const S rhs) {
writeln("copy ctor");
this.x = rhs.x;
this.y = rhs.y;
this.arr = rhs.arr.dup;
}
}
void main() {
const S[] array = [S(0, 0), S(1, 2)];
S[] copy = array.dup; // error
}
We have an issue:
Error: none of the overloads of template `object.dup` are callable using argument types `!()(const(S[]))`
But(!) if we remove the dynamic array field from the structure, everything works.
I decided to get around the problem by writing my own function to copy arrays:
T[] copyArray(T)(const T[] arr) {
T[] copy = new T[arr.length];
for (size_t i = 0; i < arr.length; i++) {
copy[i] = arr[i]; // error
}
return copy;
}
void main() {
const S[] array = [S(0, 0), S(1, 2)];
S[] copy = copyArray(array);
}
Nice, simple function, but it doesn't compile on the assignment line:
Error: cannot implicitly convert expression `arr[i]` of type `const(S)` to `S`
(The feature is the same: if we remove the dynamic array field from the structure, everything works.)
An additional variable solution worked:
T[] copyArray(T)(const T[] arr) {
T[] copy = new T[arr.length];
for (size_t i = 0; i < arr.length; i++) {
T elem = arr[i]; // copy ctor is called
copy[i] = elem; // copy ctor isn't called!
}
return copy;
}
I feel that I do not understand something, please explain what is the problem of constant structures with reference fields?
And why is the copy constructor only called once in the last example? Optimization?