I do not understand copy constructors

Learner learner at gmail.com
Thu Aug 12 15:39:40 UTC 2021


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?






More information about the Digitalmars-d-learn mailing list