On Thursday, 12 August 2021 at 14:57:16 UTC, Steven Schveighoffer
wrote:
On 8/12/21 10:08 AM, Learner wrote:
On Thursday, 12 August 2021 at 13:56:17 UTC, Paul Backus wrote:
On Thursday, 12 August 2021 at 12:10:49 UTC, Learner wrote:
That worked fine, but the codebase is @safe:
```d
cast from `int[]` to `inout(int[])` not allowed in safe code
```
So copy constructors force me to introduce trusted methods,
while that was not necessary with postblits?
A postblit would simply ignore the type qualifier--which can
lead to undefined behavior. (Scroll down to the paragraph
that begins "An unqualified postblit..." under ["Struct
Postblits"][1] in the spec.) The copy constructor merely
forces you to be honest about the safety of your code.
In your case, I would recommend encapsulating the unsafe cast
in a function like the following:
```d
T[] dupWithQualifiers(T[] array)
{
auto copy = array.dup;
return (() @trusted => cast(T[]) copy)();
}
```
You can then use this function in place of `dup` in your copy
constructor.
[1]: https://dlang.org/spec/struct.html#struct-postblit
Thank you, now everything is more clear.
A last question, if you do not mind, just to better understand
inout. It seems a shortcut to avoid repeating the same
function body for mutable, const, and immutable. Why the
following code is not equal to the single inout constructor?
struct A {
int[] data;
//this(ref return scope inout A rhs) inout { /*body*/
}
this(ref return scope Timestamp rhs) {
/*body*/ }
this(ref return scope const Timestamp rhs) const
{ /*body*/ }
this(ref return scope immutable Timestamp rhs)
immutable { /*body*/ }
}
Error: Generating an `inout` copy constructor for `struct
B` failed, therefore instances of it are uncopyable
Inout is compatible only with inout, and not with the unrolled
code it implies?
inout is not like a template. It's a separate qualifier that
generates only one function (not 3 unrolled ones).
It's sort of viral like const is viral -- all underlying pieces
have to support inout in order for you to write inout functions.
-Steve
It is not clear to me why the inout generated copy constructor of
the B structure is not able to copy the A structure.
struct A
{
int[] data;
this(ref return scope A rhs) { /*
body */ }
this(ref return scope const A rhs) const { /*
body */}
this(ref return scope immutable A rhs) immutable { /*
body */}
}
struct B
{
// default generated copy constructor, by section
14.15.6.2
this(ref return scope inout(B) src) inout
{
foreach (i, ref inout field; src.tupleof)
this.tupleof[i] = field;
}
}
Can point me to a code example of when the D generated copy
constructor fails to copy A, and why?