Bug 20424 – A constructor with a value argument of the same type as being constructed should be an error
Status
RESOLVED
Resolution
INVALID
Severity
normal
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2019-12-02T01:44:29Z
Last change time
2020-06-17T04:11:37Z
Assigned to
No Owner
Creator
Walter Bright
Comments
Comment #0 by bugzilla — 2019-12-02T01:44:29Z
extern(C) void puts(const char*);
struct S {
this(S) // should be a compile time error
{ puts("works fine"); }
}
void main() {
S a;
S b = S(a);
}
It should call itself recursively and crash. The fact that it appears to run successfully is also a bug. Copy constructors must take their first argument by reference.
https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1018.md
Comment #1 by razvan.nitu1305 — 2019-12-02T10:54:52Z
This issue is invalid. That is not a copy constructor, it is a normal constructor so there is no threat of entering in infinite recursion. The reason why it works is that the compiler simply blitts the contents of a into the stack of the constructor. I don't see any problem with this.
Comment #2 by bugzilla — 2019-12-06T09:54:46Z
An object with a copy constructor cannot be blitted into place. (Such is not allowed in C++, either, and such constructors are rejected by the compiler.)
There is no advantage to doing it anyway over passing by ref.
Comment #3 by andrei — 2019-12-09T15:30:32Z
This has been discussed and settled a long time ago.
Comment #4 by andrei — 2019-12-09T15:30:38Z
This has been discussed and settled a long time ago.
Comment #5 by razvan.nitu1305 — 2020-06-17T04:11:37Z
(In reply to Walter Bright from comment #2)
> An object with a copy constructor cannot be blitted into place. (Such is not
> allowed in C++, either, and such constructors are rejected by the compiler.)
>
> There is no advantage to doing it anyway over passing by ref.
Yes there is. You may want to construct from an rvalue, therefore you cannot use a copy constructor since rvalue references are not yet implemented in the language (there is a switch but it is only half implemented). `this(S)` does exactly that. Of course, it is illegal to have both this(S) and this(ref S).
We discussed this extensively in the DIP.