July 10, 2018
On Tuesday, 10 July 2018 14:58:09 MDT Manu via Digitalmars-d wrote:
> 2. It looks like copy constructors are used to perform assignments
> (and not constructions)... but, there is also opAssign. What gives?
>     Eg:
>       S b = a; // <- copy construction? looks like an assignment.
>     And not:
>       S b = S(a); // <- actually looks like a construction, but this
> syntax seems to not be intended (and rightly so, it's pretty terrible)

S b = a;

has never been assignment in either C++ or D. It's initialization / construction, which means that it calls a constructor - be that a postblit constructor or a copy constructor. Assignment only occurs when you're giving an existing object a new value.

And why would

S b = S(a);

not be intended? Sure, it's kind of pointless if a is an S, but if you have a copy constructor, it makes perfect sense that S(a) would work and would be pretty bizarre if it didn't, since it's explicitly calling the copy constructor. It even works right now if you give S a constructor that takes an S. It just isn't actually treated as a proper copy constructor at the moment, since that's currently the postblit constructor's job.

- Jonathan M Davis



July 10, 2018
On Tue, 10 Jul 2018 at 15:23, Jonathan M Davis via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
> On Tuesday, 10 July 2018 14:58:09 MDT Manu via Digitalmars-d wrote:
> > 2. It looks like copy constructors are used to perform assignments
> > (and not constructions)... but, there is also opAssign. What gives?
> >     Eg:
> >       S b = a; // <- copy construction? looks like an assignment.
> >     And not:
> >       S b = S(a); // <- actually looks like a construction, but this
> > syntax seems to not be intended (and rightly so, it's pretty terrible)
>
> S b = a;
>
> has never been assignment in either C++ or D. It's initialization / construction, which means that it calls a constructor - be that a postblit constructor or a copy constructor. Assignment only occurs when you're giving an existing object a new value.

I know this, but it's not syntactically obvious, it just depends on
the fact that you already know that fact... I feel a DIP about copy
construction needs to have some text explaining that, and where the
edges are.
Is an initialisation assignment can use a copy constructor, why can't
a normal assignment implicitly use a copy constructor? (implicit
destruct then copy-construct)

> And why would
>
> S b = S(a);
>
> not be intended? Sure, it's kind of pointless if a is an S, but if you have a copy constructor, it makes perfect sense that S(a) would work and would be pretty bizarre if it didn't, since it's explicitly calling the copy constructor.

But there's a super explicit `@implicit` thing written right there... so should we expect that an *explicit* call to the copy constructor is not allowed? Or maybe it is allowed and `@implicit` is a lie?

> It even works right now if you give S a constructor that takes
> an S. It just isn't actually treated as a proper copy constructor at the
> moment, since that's currently the postblit constructor's job.

Current language doesn't have `@implicit` written anywhere...
July 11, 2018
On Tuesday, 10 July 2018 at 20:58:09 UTC, Manu wrote:
> On Tue, 10 Jul 2018 at 03:50, RazvanN via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>>
>> Hi everyone!
>>
>> I managed to put together a first draft of the DIP for adding the copy constructor to the language [1]. If anyone is interested, please take a look. Suggestions and comments about technical aspects and wording are all welcome.
>>
>> Thanks,
>> RazvanN
>>
>> [1] https://github.com/dlang/DIPs/pull/129
>
> I feel there's some things missing.
>
> 1. Explain the need and reasoning behind `@implicit`... that's weird

It is a simple way of defining a copy constructor without the need of
adding new keywords and with minimal additions to the parser.

> and I don't like it at face value.
> 2. It looks like copy constructors are used to perform assignments
> (and not constructions)... but, there is also opAssign. What gives?
>     Eg:
>       S b = a; // <- copy construction? looks like an assignment.
>     And not:
>       S b = S(a); // <- actually looks like a construction, but this
> syntax seems to not be intended (and rightly so, it's pretty terrible)
> 3. In C++, copy constructors and copy assignment operators come in
> pairs (which is totally lame!), but we don't see that same pattern
> extend here, and it's not clear at all why.
> 4. Given the special rules where assignments are lifted to
> constructions, I want to know when that occurs (maybe that is already
> spec-ed wrt postblit?)
>
> - Manu

Copy construction is used solely when the object was not initialized and it
cannot be used otherwise. Consider this example:

struct A
{
    immutable int a = 7;
    @implicit this(ref A another)
    {
         this.a = A.a;      // first assignment over .init state - ok
    }

    void opAssign(A rhs)
    {
        this.a = rhs.a;
    }
}

void main()
{
    A a = A(2);
    A b = a;             //  initialization -> calls copy constructor
    b = a;               // cannot call copy constructor because it will
                         // modify immutable; call opAssign.
}

The first assignment of b calls the copy constructor and the immutable field is
initialized; later assignments to b.a will result in "modify immutable" error.
The second assignment of b cannot call the copy constructor because it would then modify an initialized immutable field. However, with opAssign the compiler knows that A.a cannot be modified because it is immutable.

July 11, 2018
> But there's a super explicit `@implicit` thing written right there... so should we expect that an *explicit* call to the copy constructor is not allowed? Or maybe it is allowed and `@implicit` is a lie?

The @implicit is there to point out that you cannot call that method
explicitly; it gets called for you implicitly when you construct an object
as a copy of another object.


July 11, 2018
On Tuesday, 10 July 2018 at 10:47:04 UTC, RazvanN wrote:
> [1] https://github.com/dlang/DIPs/pull/129

Thanks for making the DIP. I can't get this code to compile (my struct has an `int i` field):

static foreach (i, ref field; src.tupleof)
    this.tupleof[i] = field;

Error: constant value src.i cannot be ref

https://run.dlang.io/is/qeugC8

Removing `static` works. Otherwise I tried changing `ref` to `alias`:

Error: variable src cannot be read at compile time

But this shorter code seems to work fine:

this.tupleof = src.tupleof;
July 11, 2018
On Wednesday, 11 July 2018 at 07:40:32 UTC, RazvanN wrote:
>> But there's a super explicit `@implicit` thing written right there... so should we expect that an *explicit* call to the copy constructor is not allowed? Or maybe it is allowed and `@implicit` is a lie?
>
> The @implicit is there to point out that you cannot call that method
> explicitly; it gets called for you implicitly when you construct an object
> as a copy of another object.

How is this different from other types of constructors or destructors?

I also very much dislike the syntax - it makes no sense to me at all. I commented on the PR itself asking why it differs so much from C++ - specifically, what's bad about the C++ way of doing things there that we want to avoid?

Atila
July 11, 2018
On Wednesday, 11 July 2018 at 07:40:32 UTC, RazvanN wrote:
>> But there's a super explicit `@implicit` thing written right there... so should we expect that an *explicit* call to the copy constructor is not allowed? Or maybe it is allowed and `@implicit` is a lie?
>
> The @implicit is there to point out that you cannot call that method
> explicitly; it gets called for you implicitly when you construct an object
> as a copy of another object.

Can be explicit constructor overloaded with implicit constructor when both have same signature?
July 11, 2018
On Wed, 11 Jul 2018 at 00:40, RazvanN via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
> On Tuesday, 10 July 2018 at 20:58:09 UTC, Manu wrote:
> > On Tue, 10 Jul 2018 at 03:50, RazvanN via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> >>
> >> Hi everyone!
> >>
> >> I managed to put together a first draft of the DIP for adding the copy constructor to the language [1]. If anyone is interested, please take a look. Suggestions and comments about technical aspects and wording are all welcome.
> >>
> >> Thanks,
> >> RazvanN
> >>
> >> [1] https://github.com/dlang/DIPs/pull/129
> >
> > I feel there's some things missing.
> >
> > 1. Explain the need and reasoning behind `@implicit`... that's weird
>
> It is a simple way of defining a copy constructor without the
> need of
> adding new keywords and with minimal additions to the parser.

What's wrong with:
struct S {
  this(ref S copyFrom);
}

That looks like a perfectly good copy constructor declaration ;) I'm just saying, the DIP needs to explain this.

> > and I don't like it at face value.
> > 2. It looks like copy constructors are used to perform
> > assignments
> > (and not constructions)... but, there is also opAssign. What
> > gives?
> >     Eg:
> >       S b = a; // <- copy construction? looks like an
> > assignment.
> >     And not:
> >       S b = S(a); // <- actually looks like a construction, but
> > this
> > syntax seems to not be intended (and rightly so, it's pretty
> > terrible)
> > 3. In C++, copy constructors and copy assignment operators come
> > in
> > pairs (which is totally lame!), but we don't see that same
> > pattern
> > extend here, and it's not clear at all why.
> > 4. Given the special rules where assignments are lifted to
> > constructions, I want to know when that occurs (maybe that is
> > already
> > spec-ed wrt postblit?)
> >
> > - Manu
>
> Copy construction is used solely when the object was not
> initialized and it
> cannot be used otherwise. Consider this example:
>
> struct A
> {
>      immutable int a = 7;
>      @implicit this(ref A another)
>      {
>           this.a = A.a;      // first assignment over .init state
> - ok
>      }
>
>      void opAssign(A rhs)
>      {
>          this.a = rhs.a;
>      }
> }
>
> void main()
> {
>      A a = A(2);
>      A b = a;             //  initialization -> calls copy
> constructor
>      b = a;               // cannot call copy constructor because
> it will
>                           // modify immutable; call opAssign.
> }
>
> The first assignment of b calls the copy constructor and the
> immutable field is
> initialized; later assignments to b.a will result in "modify
> immutable" error.
> The second assignment of b cannot call the copy constructor
> because it would then modify an initialized immutable field.
> However, with opAssign the compiler knows that A.a cannot be
> modified because it is immutable.

Right. This is all obvious and intuitive.
What I'm hearing is that under this proposal, copy constructors and
assignment operators DO come in pairs (just like in C++), but that's
not mentioned here in this DIP. Since this proposal will introduce
that recommended pattern from C++, it may be worth mentioning.
July 11, 2018
On Wed, 11 Jul 2018 at 00:45, RazvanN via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
> > But there's a super explicit `@implicit` thing written right there... so should we expect that an *explicit* call to the copy constructor is not allowed? Or maybe it is allowed and `@implicit` is a lie?
>
> The @implicit is there to point out that you cannot call that
> method
> explicitly; it gets called for you implicitly when you construct
> an object
> as a copy of another object.

That's my point; so this is a compile error then:
S b = S(a); // <- explicit construction of copy? ie, explicit call to
stated `@implicit` function
July 11, 2018
On Wed, 11 Jul 2018 at 09:20, vit via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
> On Wednesday, 11 July 2018 at 07:40:32 UTC, RazvanN wrote:
> >> But there's a super explicit `@implicit` thing written right there... so should we expect that an *explicit* call to the copy constructor is not allowed? Or maybe it is allowed and `@implicit` is a lie?
> >
> > The @implicit is there to point out that you cannot call that
> > method
> > explicitly; it gets called for you implicitly when you
> > construct an object
> > as a copy of another object.
>
> Can be explicit constructor overloaded with implicit constructor when both have same signature?

If they've got the same signature, they should do the same thing... what's the overload for?