I do not understand copy constructors

Paul Backus snarwin at gmail.com
Thu Aug 12 16:12:39 UTC 2021


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:

```d
void f(inout(int)[] a)
{
     g(a);
}

void g(ref int[] a) {}
void g(ref const(int)[] a) {}
void g(ref immutable(int)[] a) {}
```


More information about the Digitalmars-d-learn mailing list