On Sat, 12 Oct 2024 at 03:50, Jonathan M Davis via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
On Friday, October 11, 2024 10:14:36 AM MDT Manu via Digitalmars-d wrote:
> On Thu, 10 Oct 2024, 17:56 Walter Bright via Digitalmars-d, <
>
> digitalmars-d@puremagic.com> wrote:
> > On 10/8/2024 11:54 PM, Manu wrote:
> > > Hmmmm. Well, that's not and never was a copy constructor...
> >
> > Well, it is. I don't recall when or why it was included in D.
>
> It was because postblit was riddled with problems... (maybe there's a
> lesson there?)
>
> Anyway, I thought of an issue with separating the constructor into a
> bespoke name; what happens when you do this:
>
> =this(S);
> this(S);
>
> Which is selected?

That's very clear. Move constructors simply cannot be explicitly called via
the normal constructor syntax and do not take part in overload resolution.
They have no need to. We already have the move function for moving objects
(and Martin Kinke wants to make it an intrinsic, which makes sense). So, if
you want to do an explicit move, you call move. And for implicit moves, the
compiler knows how to call the move constructor if that's necessary (and it
may be changed to just call the lowering for move as a compiler intrinsic in
order to put all of the move logic in one place).

So, if you then make an explicit constructor call with an rvalue - e.g.
S(getOtherS()) - then that will only work if you've declared a normal
constructor such as this(S). And if such a constructor exists, and you make
that explicit call with an rvalue, the move constructor would be triggered
just like it would for any other function call that took an rvalue that had
a move constructor, moving the argument into the constructor's parameter.

In addition, =this(S); should really be changed to =this(ref S); anyway,
because the move has not occurred yet, and the parameter needs to be a
reference to the object that's being passed in. Using ref explicitly avoids
the need for a weird special case with the parameter not being typed as ref
while still actually being treated as ref and not running the destructor
upon exit. And by giving the move constructor explicit syntax, we can put
ref on the parameter without conflicting with copy constructors.

> What about:
>
> =this(S);
> this(T)(T); which overlaps the concrete case?

It's a non-issue as well, because move constructors simply take no part in
overload resolution and cannot be called like a normal constructor. So,
there's never any ambiguity due to the fact that they exist.

- Jonathan M Davis

I don't even know where to start on this whole post... every single sentence is problematic. I'm essentially convinced at this point that:
1. You don't really know about move semantics; the ideas here are just bad, and you don't seem to know this... I suspect you just have no experience with move semantics, and have no associated expectations or assumptions.
2. Maybe you haven't read the DIP? Either that, or you've totally missed the point, and completely missed the merits of the design; because everything you describe here is in opposition to an efficient and semantically uniform implementation.
3. You're not actually talking about the DIP in discussion...

I don't think I have the energy to pull apart each sentence, and I doubt you're interested to hear it anyway. Maybe my post on the other thread might help get us on the same page.

On Sat, 12 Oct 2024 at 03:50, Jonathan M Davis via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
On Friday, October 11, 2024 10:14:36 AM MDT Manu via Digitalmars-d wrote:
> On Thu, 10 Oct 2024, 17:56 Walter Bright via Digitalmars-d, <
>
> digitalmars-d@puremagic.com> wrote:
> > On 10/8/2024 11:54 PM, Manu wrote:
> > > Hmmmm. Well, that's not and never was a copy constructor...
> >
> > Well, it is. I don't recall when or why it was included in D.
>
> It was because postblit was riddled with problems... (maybe there's a
> lesson there?)
>
> Anyway, I thought of an issue with separating the constructor into a
> bespoke name; what happens when you do this:
>
> =this(S);
> this(S);
>
> Which is selected?

That's very clear. Move constructors simply cannot be explicitly called via
the normal constructor syntax and do not take part in overload resolution.
They have no need to. We already have the move function for moving objects
(and Martin Kinke wants to make it an intrinsic, which makes sense). So, if
you want to do an explicit move, you call move. And for implicit moves, the
compiler knows how to call the move constructor if that's necessary (and it
may be changed to just call the lowering for move as a compiler intrinsic in
order to put all of the move logic in one place).

So, if you then make an explicit constructor call with an rvalue - e.g.
S(getOtherS()) - then that will only work if you've declared a normal
constructor such as this(S). And if such a constructor exists, and you make
that explicit call with an rvalue, the move constructor would be triggered
just like it would for any other function call that took an rvalue that had
a move constructor, moving the argument into the constructor's parameter.

In addition, =this(S); should really be changed to =this(ref S); anyway,
because the move has not occurred yet, and the parameter needs to be a
reference to the object that's being passed in. Using ref explicitly avoids
the need for a weird special case with the parameter not being typed as ref
while still actually being treated as ref and not running the destructor
upon exit. And by giving the move constructor explicit syntax, we can put
ref on the parameter without conflicting with copy constructors.

> What about:
>
> =this(S);
> this(T)(T); which overlaps the concrete case?

It's a non-issue as well, because move constructors simply take no part in
overload resolution and cannot be called like a normal constructor. So,
there's never any ambiguity due to the fact that they exist.

- Jonathan M Davis