On Thursday, 12 August 2021 at 15:39:40 UTC, Learner wrote:
> 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?
You have forgotten to add a member variable of type A
to your B
struct. If you add one, you will see the following error message:
onlineapp.d(18): Error: none of the overloads of `__ctor` are callable using a `inout` object, candidates are:
onlineapp.d(5): `onlineapp.A.this(return ref scope A rhs)`
onlineapp.d(6): `onlineapp.A.this(return ref scope const(A) rhs)`
onlineapp.d(7): `onlineapp.A.this(return ref scope immutable(A) rhs)`
(Full example: https://run.dlang.io/is/9BrpZj)
Essentially, you cannot use a mutable, const
, or immutable
copy constructor to copy an inout
object, only an inout
copy constructor.
The reason for this is a bit subtle. Normally, inout
can convert to const
, so you might expect that the const
copy constructor could be used to construct a copy of an inout
object. However, copy constructors take their arguments by ref
, and implicit conversions are not allowed for arguments passed to ref
parameters. (I cannot find a citation in the spec for this, but you can verify it yourself.)
Here's a simplified example that gives the same error:
void f(inout(int)[] a)
{
g(a);
}
void g(ref int[] a) {}
void g(ref const(int)[] a) {}
void g(ref immutable(int)[] a) {}