```
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?