Move Constructor Syntax

Jonathan M Davis newsgroup.d at jmdavisprog.com
Wed Oct 9 08:38:52 UTC 2024


On Wednesday, October 9, 2024 12:54:21 AM MDT Manu via Digitalmars-d wrote:
> On Wed, 9 Oct 2024 at 16:09, Jonathan M Davis via Digitalmars-d <
> > Aside from whatever Walter's reasoning is, there are existing constructors
> > in the wild which use
> >
> >     this(S)
> >
> > to construct a copy of a struct. This allows code such as
> >
> >     auto s = S(otherS);
> >
> > and
> >
> >     auto s = new S(otherS);
> >
> > to compile. This is particularly useful in generic code where you're
> > dealing
> > with a variant type, since without that, you have to either use a static
> > if
> > branch every time that you construct it in case the variant type is being
> > passed in, or you have to create the type with a wrapper function that
> > does
> > the static if for you. By just creating a constructor that specifically
> > takes the same type (or having a templated constructor which does the
> > appropriate static if internally), that issue is avoided. And while it can
> > certainly be argued whether that's the best approach, it's an approach
> > that
> > exists in the wild today. So, if
> >
> >     this(S)
> >
> > suddenly becomes a move constructor, existing code will have a normal
> > constructor suddenly turned into a move constructor.
>
> Hmmmm. Well, that's not and never was a copy constructor... so are we
> required to accept that that was ever correct code?

It's perfectly legal D. There is not and never has been a requirement that
you can't have a constructor that takes the same type as the original type.
Copy constructors didn't even used to exist in the language at all. You can
certainly argue that such a constructor is a bad idea, but it's perfectly
legal, and it exists in the wild. And unlike copy constructors or move
constructors, it's just a normal constructor.

> It's already problematic enough that copy constructors don't have an
> > explicit identifier of some kind (which IMHO really should be fixed).
>
> What kind of problem is a result of copy constructors not having an
> identifier?

Rather than giving the ability to indicate that a constructor is a copy
constructor, copy constructors are thoroughly restricted such that they
can't even be templated (which is a serious problem, particularly when
attributes get involved). And in order to get them to even work in many
circumstances, you're forced to put a veritable sea of attributes on them
(which of course shouldn't be necessary, but that's a separate issue),
making it so that figuring out that something is a copy constructor requires
examining the signature fairly closely. It would be _far_ cleaner to have
them clearly marked so that they would not only be easy to find, but the
compiler could tell you when you got it wrong, whereas right now, you have
to hope (and test) that you actually declared a copy constructor that gets
used as a copy constructor.

On top of that, the current situation is a royal pain with regards to
metaprogramming. Finding the constructor which is the copy constructor
requires some very careful metaprogramming to ensure that you correctly
determine which one it is - or that you correctly determine whether there's
even one there at all. And that's because it's not clearly marked as a copy
constructor in any way, shape, or form. You have to know what the exact type
is your dealing with and examine the parameters appropriately to figure it
out, and it's much harder to do than I would have ever expected, and it
really should not be that hard. It would be _so_ much cleaner if the copy
constructor were treated as distinct rather than just another constructor,
particularly since it really isn't just another constructor even if it looks
like one.

Of course, the far bigger problem with copy constructors is that the
compiler is utter garbage at generating them when a struct has any member
variables with copy constructors. It won't ever generate more than one, and
it insists on it being inout, whereas the correct solution would be to
generate all of the various combinations that are required based on the
struct's member variables (both with regards to type qualifers and
attributes). The result is that you quickly get into a disgusting mess if
you don't declare copy constructors with a very specific signature that
won't work in many situations - and with stuff like ranges where you're
calling a function that someone else wrote instead of declaring all of the
types yourself, you're just screwed, because those realistically need to
have the compiler generating the copy constructors for you instead of the
programmer declaring them manually (since whether they should even exist
depends on the template arguments, as do which overloads should exist).

As things stand, copy constructors in D are borderline garbage. They only
work well in very simple circumstances.

- Jonathan M Davis





More information about the Digitalmars-d mailing list