Thread overview
How are extra copy constructor parameters used?
Dec 30, 2021
Ali Çehreli
Dec 30, 2021
Paul Backus
Dec 30, 2021
Ali Çehreli
Dec 30, 2021
Paul Backus
Dec 30, 2021
Tejas
Dec 30, 2021
Tejas
December 29, 2021
The second item in the documentation mentions "any number of default parameters" when describing copy constructor syntax:

  https://dlang.org/spec/struct.html#struct-copy-constructor

1) I can't figure out how to use those extra parameters. For example, I can't find a special function name to call explicitly:

  S.__cctor(a, 42);  // No go

2) Unlike the examples there, I think the parameter should most usefully be defined as 'const' unless there is a special reason:

struct S {

  // const(S) instead of S:
  this(ref const(S) that) {
  }
}

Do you agree?

Thank you,
Ali
December 30, 2021
On Thursday, 30 December 2021 at 01:04:10 UTC, Ali Çehreli wrote:
> 2) Unlike the examples there, I think the parameter should most usefully be defined as 'const' unless there is a special reason:
>
> struct S {
>
>   // const(S) instead of S:
>   this(ref const(S) that) {
>   }
> }
>
> Do you agree?

When the compiler generates a copy constructor for you, it always qualifies both the source and destination objects with `inout`:

https://dlang.org/spec/struct.html#implicit-copy-constructors

Therefore, when you write your own copy constructors, you should always use `inout` if possible, so that compiler-generated copy constructors will be able to copy instances of your struct that appear as members of other structs.
December 29, 2021
On 12/29/21 5:14 PM, Paul Backus wrote:

> Therefore, when you write your own copy constructors, you should always use `inout` if possible, so that compiler-generated copy constructors will be able to copy instances of your struct that appear as members of other structs.

Excellent point. I noticed a typo in the documentation:

struct A
{
    this(ref return scope inout A rhs) immutable {}
}

That 'immutable' should be 'inout', right?

Ali
December 30, 2021
On Thursday, 30 December 2021 at 02:04:30 UTC, Ali Çehreli wrote:
> On 12/29/21 5:14 PM, Paul Backus wrote:
>
>> Therefore, when you write your own copy constructors, you should always use `inout` if possible, so that compiler-generated copy constructors will be able to copy instances of your struct that appear as members of other structs.
>
> Excellent point. I noticed a typo in the documentation:
>
> struct A
> {
>     this(ref return scope inout A rhs) immutable {}
> }
>
> That 'immutable' should be 'inout', right?

I think 'immutable' is correct here, since the usage examples look like this:

    A r1;
    const(A) r2;
    immutable(A) r3;

    // All call the same copy constructor because `inout` acts like a wildcard
    immutable(A) a = r1;
    immutable(A) b = r2;
    immutable(A) c = r3;
December 30, 2021

On Thursday, 30 December 2021 at 01:04:10 UTC, Ali Çehreli wrote:

>

The second item in the documentation mentions "any number of default parameters" when describing copy constructor syntax:

https://dlang.org/spec/struct.html#struct-copy-constructor

  1. I can't figure out how to use those extra parameters. For example, I can't find a special function name to call explicitly:

S.__cctor(a, 42); // No go

Behold the pathetic hack!

import std.stdio:writeln;

struct A
{
    this(ref return scope A rhs) inout {}                        // copy constructor
    this(ref A rhs, int b = 7) inout {        					 // copy constructor with default parameter
        if (b != 7) {
            rhs.b = b;//yes, modify the parameter, not the this object :(
            rhs.a = rhs.a;
        }        	
        else
            foreach (i, ref field; rhs.tupleof)
        		field = this.tupleof[i] ;


    }
    this(this) @disable;
    int a=4;
    int b=3;
}

void main()
{
    A a = A();
    A b = void;
    a.__ctor(b, 9); // because writing A b = A(a, 9); like a sane human is giving errors D:
    writeln(b.b);
}

Replacing a.__ctor(b, 9); with A b = A(a, 9); is yielding:

onlineapp.d(26): Error: cannot implicitly convert expression `a` of type `A` to `int`
December 30, 2021

On Thursday, 30 December 2021 at 04:42:06 UTC, Tejas wrote:

>

On Thursday, 30 December 2021 at 01:04:10 UTC, Ali Çehreli wrote:

>

The second item in the documentation mentions "any number of default parameters" when describing copy constructor syntax:

https://dlang.org/spec/struct.html#struct-copy-constructor

  1. I can't figure out how to use those extra parameters. For example, I can't find a special function name to call explicitly:

S.__cctor(a, 42); // No go

Behold the pathetic hack!

import std.stdio:writeln;

struct A
{
    this(ref return scope A rhs) inout {}                        // copy constructor
    this(ref A rhs, int b = 7) inout {        					 // copy constructor with default parameter
        if (b != 7) {
            rhs.b = b;//yes, modify the parameter, not the this object :(
            rhs.a = rhs.a;
        }        	
        else
            foreach (i, ref field; rhs.tupleof)
        		field = this.tupleof[i] ;


    }
    this(this) @disable;
    int a=4;
    int b=3;
}

void main()
{
    A a = A();
    A b = void;
    a.__ctor(b, 9); // because writing A b = A(a, 9); like a sane human is giving errors D:
    writeln(b.b);
}

Replacing a.__ctor(b, 9); with A b = A(a, 9); is yielding:

onlineapp.d(26): Error: cannot implicitly convert expression `a` of type `A` to `int`

Ehh no need to get overly dramatic, I could've done b.__ctor(a,9) in order to prevent mutation via the parameter

import std.stdio:writeln;

struct A
{
    this(ref return scope A rhs) inout {}                        // copy constructor
    this(ref return scope const A rhs, int b = 7) inout {        					 // copy constructor with default parameter
        if (b != 7) {
            this.b = b;
            this.a = rhs.a;
        }        	
        else
            foreach (i, ref inout field; rhs.tupleof)
        		this.tupleof[i] = field;


    }
    this(this) @disable;
    int a=4;
    int b=3;
}

void main()
{
    A a = A();
    A b = void;
    b.__ctor(a, 9);
    //b = A(a,9); //this still doesn't work :(
    writeln(b.b);
    writeln(b);
}