Move Constructor Syntax
Manu
turkeyman at gmail.com
Wed Oct 9 05:42:49 UTC 2024
On Sun, 6 Oct 2024 at 14:06, Walter Bright via Digitalmars-d <
digitalmars-d at puremagic.com> wrote:
> ```
> struct S { ... }
>
> this(ref S) // copy constructor
> this(this) // postblit
> this(S) // move constructor
> ~this() // destructor
>
> alias T = S;
> this(T); // also move constructor
>
> alias Q = int;
> this(Q); // regular constructor
> ```
> As the above illustrates, a move constructor cannot be distinguished from
> a
> regular constructor by syntax alone. It needs semantic analysis.
>
Yes, I would expect this.
While this seems simple enough, it isn't I have discovered to my chagrin.
> The
> overload rules in the language (including things like rvalue references
> where
> sometimes an rvalue becomes an lvalue) that the move constructors get
> confused
> with the copy constructors, leading to recursive semantic loops and other
> problems.
>
> I've struggled with this for days now.
>
Can you show us some cases?
A fix that would simplify the language and the compiler would be to have a
> unique syntax for a move constructor, instead of the ambiguous one in the
> proposal. That way, searching for a copy constructor will only yield copy
> constructors, and searching for a move constructor will only yield move
> constructors. There will be a sharp distinction between them, even in the
> source
> code. (I have seen code so dense with templates it is hard to figure out
> what
> kind of constructor it is.)
>
> Something like one of:
> ```
> 1. =this(S)
> 2. this(=S)
> 3. <-this(S)
> ```
> ?
>
> It may take a bit of getting used to. I kinda prefer (1) as it is sorta
> like
> `~this()`.
>
It's not right to distinguish move constructors, by-value argument is a
potential move opportunity.
Why aren't the regular parameter matching semantics sufficient? Can you
please give us a set of examples where the regular parameter matching
semantics are failing or infinite-looping?
The story you present is incomplete, let me enhance:
struct S { ... }
struct Other { ... }
this(ref S) // copy constructor
this(this) // postblit
this(S) // move constructor
~this() // destructor
this(Other) // move from other (Other is an rvalue here)
this(ref Other) // copy from other (Other is obviously a ref)
Likewise, I don't understand why opMove would be necessary to distinguish
from opAssign?
If you introduce opMove, then you'll end up with opIndexMove, opOpMove, etc.
Is that something you want? Assuming you want to avoid this; then I also
imagine solving for that issue would equally solve for the main constructor
case?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20241009/4073fa88/attachment-0001.htm>
More information about the Digitalmars-d
mailing list