Jump to page: 1 218  
Page
Thread overview
Move Constructor Syntax
Oct 06
Mike Shah
Oct 10
ryuukk_
Oct 11
Manu
Oct 11
Manu
Oct 06
ryuukk_
Oct 06
Dom Disc
Oct 10
zjh
Oct 10
zjh
Oct 08
vit
Oct 06
Anonymous
Oct 08
ryuukk_
Oct 08
Anonymous
Oct 09
zjh
Oct 09
zjh
Oct 07
angel
Oct 07
Daniel N
Oct 09
Manu
Oct 10
Zoadian
Oct 10
Danni Coy
Oct 11
Manu
Oct 12
Manu
Oct 12
Kagamin
Oct 12
Manu
Oct 12
Manu
Oct 12
Manu
Oct 11
Manu
Oct 14
RazvanN
Oct 15
Manu
Oct 15
RazvanN
Oct 15
RazvanN
Oct 15
Manu
Oct 15
Manu
Oct 16
RazvanN
Oct 09
Manu
Oct 11
Manu
Oct 15
Manu
Oct 15
Manu
Oct 15
Arafel
Oct 15
Manu
Oct 15
Arafel
Oct 15
Arafel
Oct 16
Arafel
Oct 16
Arafel
Oct 16
Arafel
Oct 17
Manu
Oct 17
Manu
Oct 17
Manu
Oct 17
Manu
Oct 16
Arafel
Oct 16
Arafel
Oct 16
Arafel
Oct 18
An
Oct 18
Manu
Oct 09
Kagamin
Oct 09
Manu
Oct 11
Manu
Oct 11
Kagamin
Oct 11
Kagamin
Oct 11
Kagamin
Oct 11
Manu
Oct 12
Manu
Oct 09
RazvanN
Oct 09
claptrap
Oct 10
RazvanN
Oct 10
Danni Coy
Oct 11
Manu
Oct 12
Manu
Oct 14
RazvanN
Oct 14
RazvanN
Oct 11
Manu
Oct 12
Manu
Oct 30
Manu
October 05
```
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
I forgot to mention, the C++ syntax is:
```
S(S&&)
```
so it is unambiguously distinguished at parse time.
October 05
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
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
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
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
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
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
On Sunday, 6 October 2024 at 04:04:28 UTC, Walter Bright wrote:
> ```
> struct S { ... }
>
> [...]

=this, &this or -this?
October 06
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'.
« First   ‹ Prev
1 2 3 4 5 6 7 8 9 10 11