Bug 11202 – Copy constructor is called instead of assignment on member
Status
RESOLVED
Resolution
WONTFIX
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2013-10-09T00:13:52Z
Last change time
2020-06-25T08:19:10Z
Keywords
wrong-code
Assigned to
No Owner
Creator
Denis Shelomovskii
Comments
Comment #0 by verylonglogin.reg — 2013-10-09T00:13:52Z
---
struct S
{
this(this) {}
@disable void opAssign(S);
}
struct T
{ S s; }
void main()
{
S s1, s2;
static assert(!__traits(compiles, s1 = s2));
T t1, t2;
static assert(!__traits(compiles, t1.tupleof = t2.tupleof));
static assert(!__traits(compiles, t1 = t2)); // assert fails
}
---
Comment #1 by monarchdodra — 2013-10-09T00:52:12Z
Hum... the issue is that T simply doesn't care about S's opAssign: It generates its own opAssign via "postblit-copy-move" (of all of T at once I mean).
This isn't strictly *wrong*, its just a pretty dirty way of doing things, and I'm pretty sure it's inefficient, and it definitly defeats the purpose of having an opAssign to begin with.
It *is* the only way to provide *strong* exception guarantees though, for a compiler generated elaborate opAssign, in case one of the member's opAssign throws. *Should* we guarantee strong exception safety though? I'm unsure.
Comment #2 by github-bugzilla — 2013-10-09T07:05:00Z
*** Issue 11272 has been marked as a duplicate of this issue. ***
Comment #4 by razvan.nitu1305 — 2018-09-06T12:13:40Z
opAssign for a struct is used only if it is defined for that particular struct. If the struct defines a postblit, but not an opAssign the compiler steps in and generates an opAssign which basically calls the postblit. The whole point of this design is to avoid declaring both a copy constructor and a postblit when the 2 are identical.
In this particular case, the compiler generates a postblit for T and as T does not define an opAssign, it will generate one. This is the intended behavior.
If you want to make struct T uncopyable, you should disable its postblit
>This isn't strictly *wrong*, its just a pretty dirty way of doing things, and I'm pretty sure it's inefficient, and it definitly defeats the purpose of having an opAssign to begin with.
It does not defeat the purpose of opAssign. Postblit and opAssign are 2 different things. Postblit is used for initialization and opAssign for copies, however it is a feature that the compiler generates an opAssign from the postblit when the user does not define one.
I suggest closing as wontfix.