<div dir="auto"><div><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, 11 Oct 2024, 19:21 Jonathan M Davis via Digitalmars-d, <<a href="mailto:digitalmars-d@puremagic.com">digitalmars-d@puremagic.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On Friday, October 11, 2024 12:48:45 AM MDT Manu via Digitalmars-d wrote:<br>
> They initialise an S from another S... I'm not sure what you mean by "they<br>
> do different things"?<br>
><br>
> I've been wondering, why do you need to detect that a constructor is a copy<br>
> or move constructor? That concept seems like a big internal hack. Why do<br>
> normal overload selection semantics fail to determine the proper selection?<br>
> It's not clear why it's useful or important that copy and move constructors<br>
> are separate from all other constructors? They're not special; they just<br>
> happen to accept a self-type as an init argument... the only reason I can<br>
> think, is to identify the case where they're not present, and some<br>
> copy/move code must by synthesised in lieu... what else hangs off that<br>
> knowledge?<br>
<br>
Another example of how they're treated as special is that if you declare no<br>
constructors for a struct, you get implicit construction syntax for that<br>
type. e.g.<br></blockquote></div></div><div dir="auto"><br></div><div dir="auto">You literally gave the example that I gave just one sentence prior. I'm very aware of this.</div><div dir="auto">I asked for any additional cases... can you think of any?</div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
    struct S<br>
    {<br>
        int x;<br>
        int y;<br>
    }<br>
<br>
    void main()<br>
    {<br>
        auto s1 = S(42);<br>
        auto s2 = S(42, 27);<br>
    }<br>
<br>
As soon as you declare any constructors, you no longer get that implicit<br>
construction syntax, and you can only construct the type with the<br>
constructors that you provided - except that copy constructors (and<br>
eventually move constructors) are not treated as constructors in this<br>
context. Declaring a copy constructor does not get rid of the implicit<br>
construction syntax. I've specifically had to deal with this situation when<br>
wrapping D code in order to create the same constructors that the D type has<br>
but in another language, and the fact that a copy constructor is __ctor just<br>
like all of the other constructors except for postblit constructors makes<br>
this more of a pain for no good reason.<br>
<br>
It's also the case that some metaprogramming needs to know whether a type<br>
has a copy constructor or move constructor in order to do the right thing<br>
(e.g. the lowerings for assigning slices of arrays to each other have to<br>
take that into account as do types like std.typecons.Nullable). Hiding them<br>
as normal constructors just makes that harder.<br>
<br>
All in all, I don't understand why you want to treat copy constructors or<br>
move constructors as if they were normal constructors. Unlike normal<br>
constructors, they get used when you do not call them, and you usually don't<br>
call them at all. They also have a huge impact on the semantics of how a<br>
type is actually used in many situations in a way that normal constructors<br>
do not. Treating them as normal constructors makes it harder for the user to<br>
see what's going on, and anyone generating code via metaprogramming then has<br>
a harder time doing that, because detecting them is more complicated.<br>
<br>
What benefit do you see in treating copy constructors or move constructors<br>
like they're normal constructors instead of explicitly treating them as<br>
special - especially given that the compiler already has to treat them as<br>
special in order to generate the correct code in many cases?<br></blockquote></div></div><div dir="auto"><br></div><div dir="auto">Semantic uniformity. Special casing random things is D's main claim to fame and the source of almost everything wrong with the language. </div><div dir="auto">The overload selection rules should make the proper choice.</div><div dir="auto"><br></div><div dir="auto">For what it's worth, I sympathize with your concern about template copy constructors or such; what I do, is declare `this(ref typeof(this))`, and then beside that declare my other copy-like-constructors with an if(!is(T == typeof(this)) constraint, or some similar constraint that effectively excludes the one case represented by the copy constructors.</div></div>