On Thursday, 12 August 2021 at 09:14:02 UTC, Paul Backus wrote:
On Thursday, 12 August 2021 at 08:42:27 UTC, Learner wrote:
struct A {
int[] data
this(ref return scope A rhs) { data = ths.data.dup; }
}
Generating an `inout` copy constructor for `struct B`
failed, therefore instances of it are uncopyable
What is an `inout` copy constructor? What should I change in A?
When the compiler generates a copy constructor for a struct, it
generates it with the following signature:
```d
this(ref return scope inout(typeof(this)) src) inout
```
(Source:
https://dlang.org/spec/struct.html#implicit-copy-constructors)
Notice that both the `src` object and the object being
constructed (`this`) are qualified with `inout`.
`inout` is a special type qualifier that allows the same
function to be used for mutable, `const`, and `immutable`
arguments. To make this work, the compiler imposes heavy
restrictions on what you can do with an `inout`-qualified
object--only operations that are valid on mutable, `const`,
*and* `immutable` objects are allowed for `inout`.
(Source: https://dlang.org/spec/function.html#inout-functions)
`A`'s copy constructor does not have any type qualifiers on its
`rhs` argument or its `this` reference, so both default to
mutable. In other words: `A`'s copy constructor can only be
used to construct a mutable copy from a mutable original
object. It *cannot* be used to construct an `inout` copy from
an `inout` object.
In order to make the generated copy constructor work, you need
to give `A` a copy constructor that can copy `inout` objects.
There are two possibilities here:
1. Make `A`'s copy constructor `inout`: `this(ref return scope
inout A rhs) inout`
2. Make `A`'s copy constructor `const`: `this(ref return scope
const A rhs) const`
While option 2. is not working:
struct A {
int[] data;
this(ref return scope const A rhs) const {}
}
Error: Generating an `inout` copy constructor for `struct A`
failed, therefore instances of it are uncopyable
Option .1 actually works, with an empty body, while it fails with
the actual body:
struct A {
int[] data;
this(ref return scope inout A rhs) inout { data =
rhs.data.dup; }
}
Error: cannot implicitly convert expression
`dup(cast(const(int)[])rhs.data)` of type `int[]` to
`inout(int[])`
It seems that there is no easy way to transition from a postblit
to a copy constructor, no?