October 05 Move Constructor Syntax | ||||
---|---|---|---|---|
| ||||
``` 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. 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. 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()`. |
October 05 Re: Move Constructor Syntax | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | I forgot to mention, the C++ syntax is: ``` S(S&&) ``` so it is unambiguously distinguished at parse time. |
October 05 Re: Move Constructor Syntax | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Sat, Oct 05, 2024 at 09:04:28PM -0700, Walter Bright via Digitalmars-d wrote: [...] > ``` > 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()`. [...] What about .opMove? Since .opXxx have been unofficially reserved for operator overloading, and one could argue that a move ctor is a kind of operator overloading (overloading the assignment operator). I really dislike symbols that are part of the ctor name, like C++'s operator@() overloads. It's just needlessly complex syntax. T -- Маленькие детки - маленькие бедки. |
October 05 Re: Move Constructor Syntax | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Saturday, October 5, 2024 10:04:28 PM MDT Walter Bright via Digitalmars-d 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. > > 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. > > 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.) Whatever the syntax is, I would definitely say that move constructors need a unique syntax. At work, we've had constructors that took the same type so that code such as auto a = A(otherA); and auto a = new A(otherA); would compile (though honestly, it would be nice if that syntax worked even without an explict constructor when the types match). This comes up in particular with variant types which can hold pretty much anything, in which case, templated constructors hit it quite easily. It also comes up in generic code where you're dealing with multiple types, and it's nice to not have to use static if braches just so that you can make a copy without a constructor call. And when adding copy constructors to some types, having constructors which took the same type caused grief, because for whatever reason, rvalue constructors are disallowed if you have a copy constructor. So, we had to create helper functions for constructing some types instead of being able to reliably do auto a = A(otherA); and we were forced to use static if branches in some cases to distinguish between types. I don't recall at the moment how auto ref interacts with any of this either, but it probably is disallowed with a copy constructor, and it probably will cause further issues if move constructors don't have unique syntax. In any case, we've had constructors that are not necessarily supposed to be move constructors which would match this(S), so changing this(S) to be a move constructor would cause problems for existing code. > 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()`. Honestly, I'd just argue for slapping @move on the constructor, but if I had to pick one of those three, I'd probably go with #1 simply because it would stand out more. Either way, I definitely wouldn't want #3, since it looks too much like a mistyped pointer dereference in C++. - Jonathan M Davis |
October 05 Re: Move Constructor Syntax | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | On 10/5/2024 9:33 PM, Jonathan M Davis wrote: > Honestly, I'd just argue for slapping @move on the constructor, Then people would want to slap @move on other things. > Either way, I definitely wouldn't want #3, since it looks > too much like a mistyped pointer dereference in C++. I just threw in #3 'cause I needed a third :-/ |
October 05 Re: Move Constructor Syntax | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On 10/5/2024 9:14 PM, H. S. Teoh wrote:
> What about .opMove?
I was thinking of using that for the move version of opAssign.
|
October 06 Re: Move Constructor Syntax | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On 06/10/2024 6:38 PM, Walter Bright wrote:
> On 10/5/2024 9:33 PM, Jonathan M Davis wrote:
>
> Honestly, I'd just argue for slapping @move on the constructor,
>
> Then people would want to slap @move on other things.
Does that not have desirable potential additions, once move constructors have been resolved?
For now, it can error if seen elsewhere.
|
October 06 Re: Move Constructor Syntax | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Sunday, 6 October 2024 at 05:40:40 UTC, Walter Bright wrote:
> On 10/5/2024 9:14 PM, H. S. Teoh wrote:
>> What about .opMove?
>
> I was thinking of using that for the move version of opAssign.
Perhaps opAssignMove? Slightly less ambiguous and consistent in syntax for move assignment operator.
I agree a unique constructor is the way to go for grepping code.
My vote is option 1 or 3, with some thought process below.
'=this(S)' probably the cleanest, but might confuse beginners with opEquals, opAssign, or capture syntax in C++. I imagine easiest to implement/maintain in compiler though. Still looks pretty good overall and we're use to the ~ mark on front of destructors.
'this(=S)' Wonder if this opens doors for other symbols to appear in parameters and have meaning? Are there other features we foresee where we'd want to have symbol prefixes? Probably best to avoid, as this would look better with @move, but that opens more paths toward attribute soup imo.
'->this(S)' conveys what is going on(which I like -- I switched the direction of the arrows). Easily searchable, and C and C++ programmers are used to typing it (but with a different but otherwise clear meaning). Looks a tiny bit ugly though in the code.
With any if these strategies, it seems we will then have a __move or move type function otherwise ala std::move as I understand. That seems consistent to me overall (at least for the C++ side of my brain as I understand move semantics)
|
October 06 Re: Move Constructor Syntax | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Sunday, 6 October 2024 at 04:04:28 UTC, Walter Bright wrote:
> ```
> struct S { ... }
>
> [...]
=this, &this or -this?
|
October 06 Re: Move Constructor Syntax | ||||
---|---|---|---|---|
| ||||
Posted in reply to Imperatorn | On Sunday, 6 October 2024 at 12:51:02 UTC, Imperatorn wrote:
> On Sunday, 6 October 2024 at 04:04:28 UTC, Walter Bright wrote:
>> ```
>> struct S { ... }
>>
>> [...]
>
> =this, &this or -this?
I've been partial to the idea of adding the sigil after the name.
this=(S), this<-(S), this~() - the latter being an alternate form of destructor.
but I'm not sure how well that would fit in to the existing D grammar.
These 'magical' formations were also one of my quibbles with C++.
The other toss up that none of these decorations obviously spring out as copy vs move vs construct/destruct, except possibly those involving assignment and arrow like graphics, and even those could be ambiguous.
So I'd actually favour something which somehow explicitly included the words 'move' and 'copy'.
|
Copyright © 1999-2021 by the D Language Foundation